Initial snapshot: Aliro applet, harness, Nucleo NFC10A1 reader port

Three components, all bench-validated to varying depths:

- applet/: CSA Aliro v1.0 Java Card applet for J3R180. AUTH0 + AUTH1
  expedited-standard flow end-to-end green via PC/SC bench reader
  (aliro-bench-test). Userland AES-256-GCM and HMAC-SHA-256 layered
  on top of J3R180's primitives because the card lacks both natively.
  P-256 curve params seeded explicitly per J3R180's quirk.

- harness/: Python orchestrator (aliro-trustgen, aliro-personalize,
  aliro-bench-test) for trust-bundle generation, card personalization
  via PersonalizationApplet, and PC/SC AUTH0+AUTH1 transactions. 126
  pytest cases passing.

- reader/STM32CubeExpansion_ALIRO_V1_0_0/: ST X-CUBE-ALIRO V1.0.0
  with our NFC10A1 port (NUCLEO-U545RE-Q + X-NUCLEO-NFC10A1, ST25R200
  shared with NFC09A1). nfc10-only/ project, NFC10A1 BSP shim,
  ALIRO_TRUST_OVERRIDE include into vendor's provisioning.c, and an
  ALIRO_APDU_TRACE wrapper around demoTransceiveBlocking. Boots,
  detects the J3R180, completes SELECT + AUTH0; AUTH1 currently fails
  with RFAL ERR_PROTO (0xB) — under investigation, see
  docs/plans/2026-04-20-nucleo-nfc10a1-port.md and bench-notes/.

Excluded: x-cube-aliro.zip vendor archive, harness/.venv, build dirs,
generated aliro_trust.h (contains private reader scalar), all PEMs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 10:17:46 -07:00
commit 782074f6ae
8786 changed files with 2902373 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.10)
project(Aliro LANGUAGES C)
# Collect all source files in Src
file(GLOB ALIRO_SRC "Src/*.c")
# Path to the precompiled library
set(ALIRO_LIB_PATH "${CMAKE_CURRENT_SOURCE_DIR}/Lib/aliro.a")
# Create a static library from the source files
add_library(aliro_src STATIC ${ALIRO_SRC})
# Create an interface target for the precompiled library
add_library(aliro_prebuilt STATIC IMPORTED GLOBAL)
set_target_properties(aliro_prebuilt PROPERTIES
IMPORTED_LOCATION "${ALIRO_LIB_PATH}"
)
# Create an interface target that combines both
add_library(aliro INTERFACE)
target_link_libraries(aliro INTERFACE aliro_prebuilt aliro_src)
target_include_directories(aliro INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/Inc)
# Usage:
# target_link_libraries(your_target PRIVATE aliro)
# Example
# # Add the Aliro library directory
# add_subdirectory(path/to/Aliro)
# # Link to the Aliro interface target
# target_link_libraries(my_app PRIVATE aliro)

View File

@@ -0,0 +1,307 @@
/**
******************************************************************************
* @file : ST_provisioning.h
* @brief : This file provides the provisioning profiles for User.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/** @addtogroup USER_PROVISIONING
* @{
*/
/**
* @brief Reader ID and Sub ID for User provisioning without certificate.
* @details
* Reader ID and Sub ID used for User provisioning without certificate.
*/
/* Provisioning without Certificate*/
// reader_id_User:8f9633dd856d2a156f2aee573deb11e5
// reader_sub_id_User:43815ef53299c92e95b052138133ed39
#define READER_ID_2 {0x8f, 0x96, 0x33, 0xdd, 0x85, 0x6d, 0x2a, 0x15, 0x6f, 0x2a, 0xee, 0x57, 0x3d, 0xeb, 0x11, 0xe5, 0x43, 0x81, 0x5e, 0xf5, 0x32, 0x99, 0xc9, 0x2e, 0x95, 0xb0, 0x52, 0x13, 0x81, 0x33, 0xed, 0x39}
/**
* @brief Reader public key for User provisioning without certificate.
* @details
* Reader public key for User provisioning without certificate.
*/
// reader_public_key_User:045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f
#define READER_PUB_KEY_2 {0x5b, 0xc2, 0x0b, 0x28, 0x53, 0xe1, 0x1f, 0xcb, 0x08, 0x61, 0x92, 0xd8, 0xa5, 0xd5, 0xb7, 0x82, 0x9b, 0x13, 0xd1, 0x43, 0xb0, 0xda, 0x2d, 0xe6, 0x8e, 0x1b, 0xc9, 0x4f, 0x8b, 0x01, 0x60, 0x27, 0xa8, 0x85, 0x4e, 0xae, 0x02, 0x26, 0xd4, 0x20, 0x5e, 0x8f, 0x71, 0x0d, 0x16, 0x8d, 0xa2, 0xf5, 0x7d, 0x3f, 0xa2, 0x15, 0x0b, 0x64, 0x33, 0x8d, 0x21, 0x2c, 0xe0, 0x15, 0xe2, 0x00, 0x51, 0x3f}
/**
* @brief Reader private key for User provisioning without certificate.
* @details
* Reader private key for User provisioning without certificate.
*/
// reader_private_key_User:cb64a58a5fae052d458b3bce2599a20a665987b537b157cc3cc42e1d9c652409
#define READER_PRIVATE_KEY_2 {0xcb, 0x64, 0xa5, 0x8a, 0x5f, 0xae, 0x05, 0x2d, 0x45, 0x8b, 0x3b, 0xce, 0x25, 0x99, 0xa2, 0x0a, 0x66, 0x59, 0x87, 0xb5, 0x37, 0xb1, 0x57, 0xcc, 0x3c, 0xc4, 0x2e, 0x1d, 0x9c, 0x65, 0x24, 0x09}
/**
* @brief Reader issuer public key for User provisioning without certificate.
* @details
* Not used for User provisioning without certificate.
*/
#define READER_ISSUER_PUB_KEY_2 { 0 }
/**
* @brief Reader issuer private key for User provisioning without certificate.
* @details
* Not used for User provisioning without certificate.
*/
#define READER_ISSUER_PRIVATE_KEY_2 { 0 }
/**
* @brief Reader certificate for User provisioning without certificate.
* @details
* Not used for User provisioning without certificate.
*/
#define READER_CERTIFICATE_2 { 0 }
/**
* @brief Group resolving key for User provisioning without certificate.
* @details
* Group resolving key used for User provisioning without certificate.
*/
#define GROUP_RESOLVING_KEY_2 GROUP_RESOLVING_KEY
/**
* @brief Endpoint key slot for User provisioning without certificate.
* @details
* Key slot identifier for endpoint.
*/
#define ENDPOINT_KEYSLOT_2 ENDPOINT_KEYSLOT
/**
* @brief Endpoint public key for User provisioning without certificate.
* @details
* Endpoint public key for endpoint.
*/
#define ENDPOINT_PUBLIC_KEY_2 ENDPOINT_PUBLIC_KEY
/**
* @brief Endpoint private key for User provisioning without certificate.
* @details
* Endpoint private key for endpoint.
*/
#define ENDPOINT_PRIVATE_KEY_2 ENDPOINT_PRIVATE_KEY
/**
* @brief Endpoint name for User provisioning without certificate.
* @details
* Endpoint name for endpoint.
*/
#define ENDPOINT_NAME_2 "User"
/**
* @brief Vendor specific extension for User provisioning without certificate.
* @details
* Vendor specific extension for endpoint.
*/
#define B1_VENDOR_SPECIFIC_EXTENSION_2 B1_VENDOR_SPECIFIC_EXTENSION
/**
* @brief Length of vendor specific extension for User provisioning without certificate.
* @details
* Length of vendor specific extension for endpoint.
*/
#define B1_VENDOR_SPECIFIC_EXTENSION_LEN_2 B1_VENDOR_SPECIFIC_EXTENSION_LEN
/**
* @brief Reader ID and Sub ID for User provisioning with certificate.
* @details
* Reader ID and Sub ID used for User provisioning with certificate.
*/
/* Provisioning with Certificate*/
// reader_id_cert_User:9f9633dd856d2a156f2aee573deb11e5
// reader_sub_id_cert_User:43815ef53299c92e95b052138133ed39
#define READER_ID {0x9f, 0x96, 0x33, 0xdd, 0x85, 0x6d, 0x2a, 0x15, 0x6f, 0x2a, 0xee, 0x57, 0x3d, 0xeb, 0x11, 0xe5, 0x43, 0x81, 0x5e, 0xf5, 0x32, 0x99, 0xc9, 0x2e, 0x95, 0xb0, 0x52, 0x13, 0x81, 0x33, 0xed, 0x39}
/**
* @brief Reader public key for User provisioning with certificate.
* @details
* Reader public key for User provisioning with certificate.
*/
// reader_public_key_cert_User:045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f
#define READER_PUB_KEY {0x5b, 0xc2, 0x0b, 0x28, 0x53, 0xe1, 0x1f, 0xcb, 0x08, 0x61, 0x92, 0xd8, 0xa5, 0xd5, 0xb7, 0x82, 0x9b, 0x13, 0xd1, 0x43, 0xb0, 0xda, 0x2d, 0xe6, 0x8e, 0x1b, 0xc9, 0x4f, 0x8b, 0x01, 0x60, 0x27, 0xa8, 0x85, 0x4e, 0xae, 0x02, 0x26, 0xd4, 0x20, 0x5e, 0x8f, 0x71, 0x0d, 0x16, 0x8d, 0xa2, 0xf5, 0x7d, 0x3f, 0xa2, 0x15, 0x0b, 0x64, 0x33, 0x8d, 0x21, 0x2c, 0xe0, 0x15, 0xe2, 0x00, 0x51, 0x3f}
/**
* @brief Reader private key for User provisioning with certificate.
* @details
* Reader private key for User provisioning with certificate.
*/
// reader_private_key_cert_User:cb64a58a5fae052d458b3bce2599a20a665987b537b157cc3cc42e1d9c652409
#define READER_PRIVATE_KEY {0xcb, 0x64, 0xa5, 0x8a, 0x5f, 0xae, 0x05, 0x2d, 0x45, 0x8b, 0x3b, 0xce, 0x25, 0x99, 0xa2, 0x0a, 0x66, 0x59, 0x87, 0xb5, 0x37, 0xb1, 0x57, 0xcc, 0x3c, 0xc4, 0x2e, 0x1d, 0x9c, 0x65, 0x24, 0x09}
/**
* @brief Reader issuer public key for User provisioning with certificate.
* @details
* Reader issuer public key for User provisioning with certificate.
*/
// reader_issuer_public_key_cert_User:04fbc3fdac291606a0a986862004bbe5c6188ce64098f4a65b7a6595fc31f416259141a972b916e6321dbeee22b77eec5929d80779c99f8ebe5c2588f24b24de68
#define READER_ISSUER_PUB_KEY {0xfb, 0xc3, 0xfd, 0xac, 0x29, 0x16, 0x06, 0xa0, 0xa9, 0x86, 0x86, 0x20, 0x04, 0xbb, 0xe5, 0xc6, 0x18, 0x8c, 0xe6, 0x40, 0x98, 0xf4, 0xa6, 0x5b, 0x7a, 0x65, 0x95, 0xfc, 0x31, 0xf4, 0x16, 0x25, 0x91, 0x41, 0xa9, 0x72, 0xb9, 0x16, 0xe6, 0x32, 0x1d, 0xbe, 0xee, 0x22, 0xb7, 0x7e, 0xec, 0x59, 0x29, 0xd8, 0x07, 0x79, 0xc9, 0x9f, 0x8e, 0xbe, 0x5c, 0x25, 0x88, 0xf2, 0x4b, 0x24, 0xde, 0x68}
/**
* @brief Reader issuer private key for User provisioning with certificate.
* @details
* Reader issuer private key for User provisioning with certificate.
*/
// reader_issuer_private_key_cert_User:31222ec2125a2921671e471ae67b8796668e37c0167c72bf540e4c5393599f85
#define READER_ISSUER_PRIVATE_KEY {0x31, 0x22, 0x2e, 0xc2, 0x12, 0x5a, 0x29, 0x21, 0x67, 0x1e, 0x47, 0x1a, 0xe6, 0x7b, 0x87, 0x96, 0x66, 0x8e, 0x37, 0xc0, 0x16, 0x7c, 0x72, 0xbf, 0x54, 0x0e, 0x4c, 0x53, 0x93, 0x59, 0x9f, 0x85}
/**
* @brief Reader certificate for User provisioning with certificate.
* @details
* Reader certificate for User provisioning with certificate.
*/
// reader_certificate_cert_User:3081e8040200003081e18014269e0680731d796703576be42b668a7dfe9c1e29811253544d6963726f656c656374726f6e696373820d3235313231363135343034395a830d3330313231363135343034395a840844656d6f6c6f636b854200045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f8649003046022100f1e0b84ad64aa078a039cc1be850a9d1534d52a26d6a5e137e0a710f59f12b49022100d089e452ee102cb5813eaded8625cc4b54b69835ec2e4c59c12e2a4a495dddaf
#define READER_CERTIFICATE {0x30, 0x81, 0xe8, 0x04, 0x02, 0x00, 0x00, 0x30, 0x81, 0xe1, 0x80, 0x14, 0x26, 0x9e, 0x06, 0x80, 0x73, 0x1d, 0x79, 0x67, 0x03, 0x57, 0x6b, 0xe4, 0x2b, 0x66, 0x8a, 0x7d, 0xfe, 0x9c, 0x1e, 0x29, 0x81, 0x12, 0x53, 0x54, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x73, 0x82, 0x0d, 0x32, 0x35, 0x31, 0x32, 0x31, 0x36, 0x31, 0x35, 0x34, 0x30, 0x34, 0x39, 0x5a, 0x83, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x31, 0x36, 0x31, 0x35, 0x34, 0x30, 0x34, 0x39, 0x5a, 0x84, 0x08, 0x44, 0x65, 0x6d, 0x6f, 0x6c, 0x6f, 0x63, 0x6b, 0x85, 0x42, 0x00, 0x04, 0x5b, 0xc2, 0x0b, 0x28, 0x53, 0xe1, 0x1f, 0xcb, 0x08, 0x61, 0x92, 0xd8, 0xa5, 0xd5, 0xb7, 0x82, 0x9b, 0x13, 0xd1, 0x43, 0xb0, 0xda, 0x2d, 0xe6, 0x8e, 0x1b, 0xc9, 0x4f, 0x8b, 0x01, 0x60, 0x27, 0xa8, 0x85, 0x4e, 0xae, 0x02, 0x26, 0xd4, 0x20, 0x5e, 0x8f, 0x71, 0x0d, 0x16, 0x8d, 0xa2, 0xf5, 0x7d, 0x3f, 0xa2, 0x15, 0x0b, 0x64, 0x33, 0x8d, 0x21, 0x2c, 0xe0, 0x15, 0xe2, 0x00, 0x51, 0x3f, 0x86, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xf1, 0xe0, 0xb8, 0x4a, 0xd6, 0x4a, 0xa0, 0x78, 0xa0, 0x39, 0xcc, 0x1b, 0xe8, 0x50, 0xa9, 0xd1, 0x53, 0x4d, 0x52, 0xa2, 0x6d, 0x6a, 0x5e, 0x13, 0x7e, 0x0a, 0x71, 0x0f, 0x59, 0xf1, 0x2b, 0x49, 0x02, 0x21, 0x00, 0xd0, 0x89, 0xe4, 0x52, 0xee, 0x10, 0x2c, 0xb5, 0x81, 0x3e, 0xad, 0xed, 0x86, 0x25, 0xcc, 0x4b, 0x54, 0xb6, 0x98, 0x35, 0xec, 0x2e, 0x4c, 0x59, 0xc1, 0x2e, 0x2a, 0x4a, 0x49, 0x5d, 0xdd, 0xaf}
/**
* @brief Reader long certificate for User provisioning with certificate.
* @details
* Reader long certificate for User provisioning with certificate.
*/
// reader_certificate_cert_long_User:3082010b0402000030820103801412c2a20661964981c92cd242e6d06d2ce8053b4f811f53544d6963726f656c656374726f6e69637353544d6963726f656c65637472820d3235313231363135343034395a830d3330313231363135343034395a841f44656d6f6c6f636b44656d6f6c6f636b44656d6f6c6f636b44656d6f6c6f63854200045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f864700304402206aef6a6cf112f97c16c1e844f65ef3913cbe388b4e9ee8795fbc08f240f5337702205da03ad102a63e1095da5692a463db8d18866b07e5580f6ef0f28c5153ac3400
#define READER_LONG_CERTIFICATE {0x30, 0x82, 0x01, 0x0b, 0x04, 0x02, 0x00, 0x00, 0x30, 0x82, 0x01, 0x03, 0x80, 0x14, 0x12, 0xc2, 0xa2, 0x06, 0x61, 0x96, 0x49, 0x81, 0xc9, 0x2c, 0xd2, 0x42, 0xe6, 0xd0, 0x6d, 0x2c, 0xe8, 0x05, 0x3b, 0x4f, 0x81, 0x1f, 0x53, 0x54, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x73, 0x53, 0x54, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x82, 0x0d, 0x32, 0x35, 0x31, 0x32, 0x31, 0x36, 0x31, 0x35, 0x34, 0x30, 0x34, 0x39, 0x5a, 0x83, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x31, 0x36, 0x31, 0x35, 0x34, 0x30, 0x34, 0x39, 0x5a, 0x84, 0x1f, 0x44, 0x65, 0x6d, 0x6f, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6d, 0x6f, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6d, 0x6f, 0x6c, 0x6f, 0x63, 0x6b, 0x44, 0x65, 0x6d, 0x6f, 0x6c, 0x6f, 0x63, 0x85, 0x42, 0x00, 0x04, 0x5b, 0xc2, 0x0b, 0x28, 0x53, 0xe1, 0x1f, 0xcb, 0x08, 0x61, 0x92, 0xd8, 0xa5, 0xd5, 0xb7, 0x82, 0x9b, 0x13, 0xd1, 0x43, 0xb0, 0xda, 0x2d, 0xe6, 0x8e, 0x1b, 0xc9, 0x4f, 0x8b, 0x01, 0x60, 0x27, 0xa8, 0x85, 0x4e, 0xae, 0x02, 0x26, 0xd4, 0x20, 0x5e, 0x8f, 0x71, 0x0d, 0x16, 0x8d, 0xa2, 0xf5, 0x7d, 0x3f, 0xa2, 0x15, 0x0b, 0x64, 0x33, 0x8d, 0x21, 0x2c, 0xe0, 0x15, 0xe2, 0x00, 0x51, 0x3f, 0x86, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x6a, 0xef, 0x6a, 0x6c, 0xf1, 0x12, 0xf9, 0x7c, 0x16, 0xc1, 0xe8, 0x44, 0xf6, 0x5e, 0xf3, 0x91, 0x3c, 0xbe, 0x38, 0x8b, 0x4e, 0x9e, 0xe8, 0x79, 0x5f, 0xbc, 0x08, 0xf2, 0x40, 0xf5, 0x33, 0x77, 0x02, 0x20, 0x5d, 0xa0, 0x3a, 0xd1, 0x02, 0xa6, 0x3e, 0x10, 0x95, 0xda, 0x56, 0x92, 0xa4, 0x63, 0xdb, 0x8d, 0x18, 0x86, 0x6b, 0x07, 0xe5, 0x58, 0x0f, 0x6e, 0xf0, 0xf2, 0x8c, 0x51, 0x53, 0xac, 0x34, 0x00}
/**
* @brief Reader short certificate for User provisioning with certificate.
* @details
* Reader short certificate for User provisioning with certificate.
*/
// reader_certificate_cert_short_User:3081940402000030818d854200045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f8647003044022004060b7ec96115558aaa21686b8a5cd76c3cf0ef0214ef3d93189b789624c48f022031664dc32677ff6eba89126ebd212f903dc0dc8a4c837ebb306e062ba2231be2
#define READER_SHORT_CERTIFICATE {0x30, 0x81, 0x94, 0x04, 0x02, 0x00, 0x00, 0x30, 0x81, 0x8d, 0x85, 0x42, 0x00, 0x04, 0x5b, 0xc2, 0x0b, 0x28, 0x53, 0xe1, 0x1f, 0xcb, 0x08, 0x61, 0x92, 0xd8, 0xa5, 0xd5, 0xb7, 0x82, 0x9b, 0x13, 0xd1, 0x43, 0xb0, 0xda, 0x2d, 0xe6, 0x8e, 0x1b, 0xc9, 0x4f, 0x8b, 0x01, 0x60, 0x27, 0xa8, 0x85, 0x4e, 0xae, 0x02, 0x26, 0xd4, 0x20, 0x5e, 0x8f, 0x71, 0x0d, 0x16, 0x8d, 0xa2, 0xf5, 0x7d, 0x3f, 0xa2, 0x15, 0x0b, 0x64, 0x33, 0x8d, 0x21, 0x2c, 0xe0, 0x15, 0xe2, 0x00, 0x51, 0x3f, 0x86, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x04, 0x06, 0x0b, 0x7e, 0xc9, 0x61, 0x15, 0x55, 0x8a, 0xaa, 0x21, 0x68, 0x6b, 0x8a, 0x5c, 0xd7, 0x6c, 0x3c, 0xf0, 0xef, 0x02, 0x14, 0xef, 0x3d, 0x93, 0x18, 0x9b, 0x78, 0x96, 0x24, 0xc4, 0x8f, 0x02, 0x20, 0x31, 0x66, 0x4d, 0xc3, 0x26, 0x77, 0xff, 0x6e, 0xba, 0x89, 0x12, 0x6e, 0xbd, 0x21, 0x2f, 0x90, 0x3d, 0xc0, 0xdc, 0x8a, 0x4c, 0x83, 0x7e, 0xbb, 0x30, 0x6e, 0x06, 0x2b, 0xa2, 0x23, 0x1b, 0xe2}
/**
* @brief Group resolving key for User provisioning with certificate.
* @details
* Group resolving key used for User provisioning with certificate.
*/
// group_resolving_key_User:0375ed63685570f6b2168eab7296ec01
#define GROUP_RESOLVING_KEY {0x03, 0x75, 0xed, 0x63, 0x68, 0x55, 0x70, 0xf6, 0xb2, 0x16, 0x8e, 0xab, 0x72, 0x96, 0xec, 0x01}
/**
* @brief Endpoint key slot for User provisioning with certificate.
* @details
* Key slot identifier for endpoint.
*/
// endpoint_key_slot_cert_Alice_User:54b54e27d515ac4c
#define ENDPOINT_KEYSLOT {0x54, 0xb5, 0x4e, 0x27, 0xd5, 0x15, 0xac, 0x4c}
/**
* @brief Endpoint public key for User provisioning with certificate.
* @details
* Endpoint public key for endpoint.
*/
// endpoint_public_key_cert_Alice_User:04773f9aa84ac9705161c490a2dba0b4a19a3d2a78705a801cff924e26357e4213191db83789a25916e4accea1fd6f09239b4cf2dd0d05b33b72d8a3a642e30866
#define ENDPOINT_PUBLIC_KEY {0x77, 0x3f, 0x9a, 0xa8, 0x4a, 0xc9, 0x70, 0x51, 0x61, 0xc4, 0x90, 0xa2, 0xdb, 0xa0, 0xb4, 0xa1, 0x9a, 0x3d, 0x2a, 0x78, 0x70, 0x5a, 0x80, 0x1c, 0xff, 0x92, 0x4e, 0x26, 0x35, 0x7e, 0x42, 0x13, 0x19, 0x1d, 0xb8, 0x37, 0x89, 0xa2, 0x59, 0x16, 0xe4, 0xac, 0xce, 0xa1, 0xfd, 0x6f, 0x09, 0x23, 0x9b, 0x4c, 0xf2, 0xdd, 0x0d, 0x05, 0xb3, 0x3b, 0x72, 0xd8, 0xa3, 0xa6, 0x42, 0xe3, 0x08, 0x66}
/**
* @brief Endpoint private key for User provisioning with certificate.
* @details
* Endpoint private key for endpoint.
*/
// endpoint_private_key_cert_Alice_User:db1d6524990aecce49c3c5c79ee41361b01b49302eac1cc5f9decd0d1058d14e
#define ENDPOINT_PRIVATE_KEY {0xdb, 0x1d, 0x65, 0x24, 0x99, 0x0a, 0xec, 0xce, 0x49, 0xc3, 0xc5, 0xc7, 0x9e, 0xe4, 0x13, 0x61, 0xb0, 0x1b, 0x49, 0x30, 0x2e, 0xac, 0x1c, 0xc5, 0xf9, 0xde, 0xcd, 0x0d, 0x10, 0x58, 0xd1, 0x4e}
/**
* @brief Endpoint name for User provisioning with certificate.
* @details
* Endpoint name for endpoint.
*/
#define ENDPOINT_NAME "User_cert"
/**
* @brief Vendor specific extension for User provisioning with certificate.
* @details
* Vendor specific extension for endpoint.
*/
#define B1_VENDOR_SPECIFIC_EXTENSION "ST Rooms"
/**
* @brief Vendor specific extension length for User provisioning with certificate.
* @details
* Vendor specific extension length for endpoint.
*/
#define B1_VENDOR_SPECIFIC_EXTENSION_LEN 8
/**
* @brief Credential issuer public key for User provisioning.
* @details
* Credential issuer public key for stepup menager.
*/
#define CREDENTIAL_ISSUER_PUB_KEY_2 { 0x7B, 0xA3, 0x19, 0x38, 0x49, 0x2E, 0x3F, 0x5E, 0x97, 0xBC, 0x91, 0x80, 0x6B, 0x58, 0x35, 0xB5, 0xD9, 0xE4, 0x26, 0x60, 0x91, 0x39, 0x00, 0x67, 0x11, 0xE5, 0xFB, 0x7A, 0x67, 0x0E, 0xE4, 0xE1, 0x2F, 0xC9, 0xF2, 0x53, 0x96, 0xC0, 0x13, 0xCC, 0x20, 0x16, 0x60, 0x29, 0xD7, 0x61, 0xA1, 0x05, 0xDE, 0xA5, 0xE0, 0x71, 0xE8, 0x4A, 0x9E, 0x49, 0x99, 0x20, 0x52, 0x4C, 0xE2, 0x30, 0x11, 0x37 }
/**
* @brief Credential issuer private key for User provisioning.
* @details
* Credential issuer private key for stepup menager.
*/
#define CREDENTIAL_ISSUER_PRIVATE_KEY_2 { 0 }
/**
* @}
*/
/* Test Harness configuration
{
"test_parameters": {
"dut_reader_public_key": "045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f",
"dut_reader_group_identifier": "8f9633dd856d2a156f2aee573deb11e5",
"dut_reader_issuer_public_key": "04fbc3fdac291606a0a986862004bbe5c6188ce64098f4a65b7a6595fc31f416259141a972b916e6321dbeee22b77eec5929d80779c99f8ebe5c2588f24b24de68",
"dut_reader_issuer_group_identifier": "9f9633dd856d2a156f2aee573deb11e5",
"dut_reader_group_sub_identifier": "43815ef53299c92e95b052138133ed39",
"dut_reader_group_resolving_key": "0375ed63685570f6b2168eab7296ec01",
"th_access_credential_private_key": "db1d6524990aecce49c3c5c79ee41361b01b49302eac1cc5f9decd0d1058d14e",
"th_access_credential_public_key": "04773f9aa84ac9705161c490a2dba0b4a19a3d2a78705a801cff924e26357e4213191db83789a25916e4accea1fd6f09239b4cf2dd0d05b33b72d8a3a642e30866",
"th_reader_private_key": "8aefdff8d5b47aa9a3edbac7a345ed2221021512fd55abde3b8ee0f208952693",
"th_reader_public_key": "043928f322019d4757893bde6a0fe5e13e3e537b9ca0f549c0bd2f40f79060252a0a4f291192157a95cb6eb202759428c00cd834998c5d0eab192ee8873c5d34ee",
"th_reader_group_identifier": "00113344667799AA00113344667799AA",
"th_reader_sub_group_identifier": "113344667799AA00113344667799AA00",
"th_reader_certificate": "308201523081f9a003020102020101300a06082a8648ce3d0403023011310f300d06035504030c06697373756572301e170d3230303130313030303030305a170d3439303130313030303030305a30123110300e06035504030c077375626a6563743059301306072a8648ce3d020106082a8648ce3d030107034200043928f322019d4757893bde6a0fe5e13e3e537b9ca0f549c0bd2f40f79060252a0a4f291192157a95cb6eb202759428c00cd834998c5d0eab192ee8873c5d34eea341303f301f0603551d230418301680143fb5efecb9f0a8b253e4b6788dc15a5913f7c763300c0603551d130101ff04023000300e0603551d0f0101ff040403020780300a06082a8648ce3d04030203480030450220296b57afcb0f1f86e7c3e76b16f82ea0737e8105d5c5e03f3333e6ef9193c80d022100909083e76eaaf0430c7639159b00620d0c6a40fdb6e11ec52ed5bdd3dfb1706f",
"th_reader_group_resolving_key": "0375ed63685570f6b2168eab7296ec01",
"th_reader_spsm": "0080"
}
}
*/
/* Reader provisioning
{
"MaxDevices": 8,
"reader_identifier": "8f9633dd856d2a156f2aee573deb11e543815ef53299c92e95b052138133ed39",
"reader_PrivK": "cb64a58a5fae052d458b3bce2599a20a665987b537b157cc3cc42e1d9c652409",
"reader_PubK": "045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f",
"issuer_Private": "31222ec2125a2921671e471ae67b8796668e37c0167c72bf540e4c5393599f85",
"issuer_Public": "04fbc3fdac291606a0a986862004bbe5c6188ce64098f4a65b7a6595fc31f416259141a972b916e6321dbeee22b77eec5929d80779c99f8ebe5c2588f24b24de68",
"certificate_data": "3081e8040200003081e18014269e0680731d796703576be42b668a7dfe9c1e29811253544d6963726f656c656374726f6e696373820d3235313231363135343034395a830d3330313231363135343034395a840844656d6f6c6f636b854200045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f8649003046022100f1e0b84ad64aa078a039cc1be850a9d1534d52a26d6a5e137e0a710f59f12b49022100d089e452ee102cb5813eaded8625cc4b54b69835ec2e4c59c12e2a4a495dddaf",
"b1VendorSpecificExtension": "ST Rooms",
"Devices": [
{
"Name": "Alice",
"endpoint_Keyslot": "54b54e27d515ac4c",
"endpoint_PubK": "04773f9aa84ac9705161c490a2dba0b4a19a3d2a78705a801cff924e26357e4213191db83789a25916e4accea1fd6f09239b4cf2dd0d05b33b72d8a3a642e30866",
"endpoint_PrivK": "db1d6524990aecce49c3c5c79ee41361b01b49302eac1cc5f9decd0d1058d14e"
}
]
}
*/
/* Terminal command for provisioning
// setRDiden-8f9633dd856d2a156f2aee573deb11e543815ef53299c92e95b052138133ed39
// setRDprvk-cb64a58a5fae052d458b3bce2599a20a665987b537b157cc3cc42e1d9c652409
// setRDpubk-045bc20b2853e11fcb086192d8a5d5b7829b13d143b0da2de68e1bc94f8b016027a8854eae0226d4205e8f710d168da2f57d3fa2150b64338d212ce015e200513f
// setDEVpbk-04773f9aa84ac9705161c490a2dba0b4a19a3d2a78705a801cff924e26357e4213191db83789a25916e4accea1fd6f09239b4cf2dd0d05b33b72d8a3a642e30866
// setRDgrrk-0375ed63685570f6b2168eab7296ec01
// setRisspk-04fbc3fdac291606a0a986862004bbe5c6188ce64098f4a65b7a6595fc31f416259141a972b916e6321dbeee22b77eec5929d80779c99f8ebe5c2588f24b24de68
*/

View File

@@ -0,0 +1,708 @@
/**
******************************************************************************
* @file : app_aliro.h
* @brief : Header for app_aliro.c file.
* This file contains the public declarations for the Aliro demo.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _APP_ALIRO_H_
#define _APP_ALIRO_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NFCBLE
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include "st_errno.h"
#include "ACWG_Security.h"
#include "provisioning.h"
#if defined(STM32U545xx) || defined(STM32U585xx)
#include "stm32u5xx_hal.h"
#include "stm32u5xx_nucleo.h"
#include "log_module_u5.h"
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...);
#endif //defined(STM32U545xx) || defined(STM32U585xx)
#if defined(STM32U385xx)
#include "stm32u3xx_hal.h"
#include "stm32u3xx_nucleo.h"
#include "log_module_u3.h"
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...);
#endif //defined(STM32U385xx)
#if defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
#include "stm32wbaxx_hal.h"
#include "stm32wbaxx_nucleo.h"
#include "log_module.h"
#endif //defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
/** @addtogroup Aliro_app_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @enum verblevel_t
* @brief Verbosity levels for logging.
*/
typedef enum _verblevel
{
VERB_NULL=0, /**< No output */
VERB_ALWAYS=1, /**< Always output */
VERB_CRITICAL=2, /**< Critical output */
VERB_ERROR=3, /**< Error output */
VERB_NORMAL=4, /**< Normal output */
VERB_VERBOSE=5, /**< Verbose output */
VERB_INFO=6 /**< Informational output */
}verblevel_t;
/**
* @enum timeStampsPos_t
* @brief Timestamp positions for performance measurement.
*/
typedef enum _timeStampsPos
{
SELECT_APP_POS, /**< Application selection */
END_SELECT_APP_POS, /**< End of application selection */
AUTH0_POS, /**< Start authentication 0 */
END_AUTH0_POS, /**< End authentication 0 */
LOADCERT_POS, /**< Certificate loading */
END_LOADCERT_POS, /**< End certificate loading */
AUTH1_POS, /**< Start authentication 1 */
END_AUTH1_POS, /**< End authentication 1 */
CONTROL_FLOW_POS, /**< Control flow */
END_CONTROL_FLOW_POS, /**< End control flow */
EXCHANGE_POS, /**< Data exchange */
END_EXCHANGE_POS, /**< End data exchange */
STEPUP_POS, /**< Step-up */
END_STEPUP_POS, /**< End step-up */
DOOR_IS_OPENED_POS, /**< Door opened */
DOOR_IS_CLOSED_POS, /**< Door closed */
DOOR_IS_DISARMED_POS, /**< Door disarmed */
DON_T_KNOW_POS, /**< Unknown state */
DERIVE_PERSISTENT_KEYS_POS, /**< Derivation of persistent keys */
END_DERIVE_PERSISTENT_KEYS_POS,/**< End derivation of persistent keys */
ELAPSED_TIME_POS, /**< Elapsed time */
NUM_TIMESTAMPS /**< Total number of timestamps (do not change) */
}timeStampsPos_t;
/**
* @struct statItem_t
* @brief Structure for managing timestamps and statistics.
*/
typedef struct _statItem
{
timeStampsPos_t pos; /**< Timestamp position */
char title[10]; /**< Title */
uint8_t toPrint; /**< Print flag */
uint32_t ts; /**< Timestamp value */
}statItem_t;
/**
* @struct alirosvc_param_t
* @brief Aliro service parameters.
*/
typedef struct _alirosvc_param
{
uint8_t proposedSPSM[2]; /**< Proposed SPSM */
uint8_t protVerSupportedLen; /**< Supported protocol version length */
uint8_t supportedProtocolVersion[4]; /**< Supported protocol versions */
uint8_t selectedProtocolVersion[2]; /**< Selected protocol version */
uint8_t featuresSupportedLen; /**< Supported features length */
uint8_t featuresSupported[1]; /**< Supported features */
}
alirosvc_param_t;
/**
* @}
*/
/** @addtogroup Aliro_app_Exported_Variables
* @{
*/
/* Exported variables ------------------------------------------------------------*/
/**
* @brief Aliro protocol versions supported.
*/
extern uint32_t xProtocolVersionSupported;
/**
* @brief Current verbosity level.
*/
extern verblevel_t nVerbosityLevel;
/**
* @brief NFC session context.
*/
extern ACWG_SessionContext_t context_nfc;
/**
* @brief NFC session context.
*/
extern ACWG_SessionContext_t context_ble;
/**
* @}
*/
/** @addtogroup Aliro_app_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
#define VERBOSITY_SET nVerbosityLevel /**< Macro to get the current verbosity level */
#define ALIRO_MEASURE_PERFORMANCE 0 /**< Enable performance measurement */
#define ALIRO_CERTIFICATION_TEST 1 /**< Enable certification test */
//0x40 --> Bit 6: Bluetooth LE-Only Aliro flow supported.
//0x80 --> Bit 7: Bluetooth LE + UWB Aliro flow supported.
#define BLE_RKE_ALIRO_FLOW_SUPPORTED 0x40 /**< Bit 6: BLE-only Aliro flow supported */
#define BLE_UWB_ALIRO_FLOW_SUPPORTED 0x80 /**< Bit 7: BLE + UWB Aliro flow supported */
#define BLE_ALIRO_FLOWS_SUPPORTED (BLE_UWB_ALIRO_FLOW_SUPPORTED | BLE_RKE_ALIRO_FLOW_SUPPORTED) /**< Macro for supported Aliro flows */
#define ALIRO_RTC_SET_STATUS_IAR 0x00F4 /**< RTC IAR status */
#define ALIRO_RTC_SET_STATUS_GOOD 0x34F4 /**< RTC good status */
#define TIMEOUT_PREPARE_RANGING_DEFAULT 20000 /** Default timeout (ms) for prepare ranging operation. */
#define TIMEOUT_EXECUTE_RANGING_DEFAULT 70000 /** Default timeout (ms) for execute ranging operation. */
#define TIMEOUT_SUSPEND_RANGING_DEFAULT 10000 /** Default timeout (ms) for suspend ranging operation. */
#define TIMEOUT_RESUME_RANGING_DEFAULT 20000 /** Default timeout (ms) for resume ranging operation. */
#define TIMEOUT_DOOR_OPERATION_DEFAULT 20000 /** Default timeout (ms) for door operation. */
#if defined (ST25R200)
#define X_NUCLEO_NFC_NAME "X-NUCLEO-NFC09A1/NFC10A1"
#endif //defined (ST25R200)
#if defined (ST25R500)
#define X_NUCLEO_NFC_NAME "X-NUCLEO-NFC12A1"
#endif //defined (ST25R200)
#if USE_GEN2
#define ALIRO_BLE 1
#define H_ALIRO_UART huart1
#define HH_ALIRO_UART &H_ALIRO_UART
#define H_TIM htim2
extern RTC_HandleTypeDef hrtc;
#define ALIRO_HRTC hrtc
#define ALIRO_RTC_BKP_TIME RTC_BKP_DR10
#define LD3_Pin GPIO_PIN_0
#define LD3_GPIO_Port GPIOE
#define LD2_Pin GPIO_PIN_1
#define LD2_GPIO_Port GPIOE
//sector 125
#define PROVISIONING_SECTOR 253
#define PROVISIONING_START_ADDRESS (0x08000000+PROVISIONING_SECTOR*0x2000) //0x081fa000
//sector 124
#define PROVISIONING_JSON_SECTOR 252
#define PROVISIONING_JSON_START_ADDRESS (0x08000000+PROVISIONING_JSON_SECTOR*0x2000) //0x081f8000
#else //USE_GEN2
#if defined(STM32WBA52xx)||defined(STM32WBA55xx)
#define ALIRO_BLE 1
#define H_ALIRO_UART huart1
#define HH_ALIRO_UART &H_ALIRO_UART
#define H_TIM htim2
extern RTC_HandleTypeDef hrtc;
#define ALIRO_HRTC hrtc
#define ALIRO_RTC_BKP_TIME RTC_BKP_DR10
#define LD3_Pin GPIO_PIN_8
#define LD3_GPIO_Port GPIOB
#define LD2_Pin GPIO_PIN_9
#define LD2_GPIO_Port GPIOA
//sector 125
#define PROVISIONING_SECTOR 123
#define PROVISIONING_START_ADDRESS (0x08000000+PROVISIONING_SECTOR*0x2000) //0x080fa000
//sector 124
#define PROVISIONING_JSON_SECTOR 122
#define PROVISIONING_JSON_START_ADDRESS (0x08000000+PROVISIONING_JSON_SECTOR*0x2000) //0x080f8000
#endif //defined(STM32WBA52xx)||defined(STM32WBA55xx)
#ifdef STM32WBA65xx
#define ALIRO_BLE 1
#define H_ALIRO_UART huart1
#define HH_ALIRO_UART &H_ALIRO_UART
#define H_TIM htim2
extern RTC_HandleTypeDef hrtc;
#define ALIRO_HRTC hrtc
#define ALIRO_RTC_BKP_TIME RTC_BKP_DR10
#define LD3_Pin GPIO_PIN_0
#define LD3_GPIO_Port GPIOE
#define LD2_Pin GPIO_PIN_1
#define LD2_GPIO_Port GPIOE
//sector 125
#define PROVISIONING_SECTOR 253
#define PROVISIONING_START_ADDRESS (0x08000000+PROVISIONING_SECTOR*0x2000) //0x081fa000
//sector 124
#define PROVISIONING_JSON_SECTOR 252
#define PROVISIONING_JSON_START_ADDRESS (0x08000000+PROVISIONING_JSON_SECTOR*0x2000) //0x081f8000
#endif //STM32WBA65xx
#if defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
extern EXTI_HandleTypeDef H_EXTI_13;
extern UART_HandleTypeDef huart1;
#define HH_ALIRO_UART &huart1
#define H_ALIRO_UART huart1
#define H_TIM htim2
#define LD3_Pin GPIO_PIN_8
#define LD3_GPIO_Port GPIOB
#define LD2_Pin GPIO_PIN_4
#define LD2_GPIO_Port GPIOC
//sector 125
#define PROVISIONING_SECTOR 63
#define PROVISIONING_START_ADDRESS (0x08000000+PROVISIONING_SECTOR*0x2000) //0x081fa000
//sector 124
#define PROVISIONING_JSON_SECTOR 62
#define PROVISIONING_JSON_START_ADDRESS (0x08000000+PROVISIONING_JSON_SECTOR*0x2000) //0x081f8000
#endif //defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
#endif //USE_GEN2
#if defined ALIRO_HRTC
#define USE_RTC 1
#endif //defined ALIRO_HRTC
#define CLEAR_SCREEN_COMMAND "\033[2J\r\n"
#define TEXT_COLOR_1 "\033[0;32m" //green
#define TEXT_COLOR_GREEN "\033[0;32m" //green
#define TEXT_COLOR_2 "\033[0;33m"
#define TEXT_COLOR_YELLOW "\033[0;33m"
#define TEXT_COLOR_3 "\033[0;31m"
#define TEXT_COLOR_RED "\033[0;31m"
#define TEXT_COLOR_4 "\033[0;36m"
#define TEXT_COLOR_CYAN "\033[0;36m"
#define TEXT_COLOR_BLU "\033[0;34m"
#define TEXT_COLOR_VIOLET "\033[0;35m"
#define TEXT_COLOR_GRAY "\033[0;37m"
#define TEXT_COLOR_NOIR "\033[0;30m"
#define TEXT_COLOR_DEFAULT "\033[0;39m"
//Background
#define TEXT_BACKGROUND_COLOR_BLACK "\033[40m"
#define TEXT_BACKGROUND_COLOR_RED "\033[41m"
#define TEXT_BACKGROUND_COLOR_GREEN "\033[42m"
#define TEXT_BACKGROUND_COLOR_YELLOW "\033[43m"
#define TEXT_BACKGROUND_COLOR_BLUE "\033[44m"
#define TEXT_BACKGROUND_COLOR_PURPLE "\033[45m"
#define TEXT_BACKGROUND_COLOR_CYAN "\033[46m"
#define TEXT_BACKGROUND_COLOR_WHITE "\033[47m"
#define TEXT_TEST_COLOR "\033[7;34m"
#define TEXT_RESET "\033[0m"
#define TEXT_BOLD "\033[1m" //used to make ligth color
#define TEXT_UNDERSCORE "\033[4m"
#define TEXT_BLINK "\033[5m"
#define TEXT_REVERSE "\033[7m"
#define TEXT_CONCEALED "\033[8m"
#define TEXT_COLOR_ESCAPE_CHAR '\033'
#define VERB_STATISTICS VERB_INFO
#define VERB_STATISTICS_REPORT VERB_CRITICAL
#define VERB_STATE_TITLE VERB_NORMAL
#define VERB_FN_NAME VERB_VERBOSE
#define VERB_TERMINAL VERB_NORMAL
/**
* @}
*/
/** @addtogroup Aliro_app_Exported_Macros
* @{
*/
/* Exported macro ------------------------------------------------------------*/
#if ALIRO_MEASURE_PERFORMANCE
#define RESET_TIME_STAMP() do{ ResetTimeStamp();ResetAllSavedTimeStamps(); }while(0)
#define PRINT_TIME_STAMP(pos) do{ SaveTimeStamp(pos);/*PrintTimeStamp(label);*/ }while(0)
#define TIME_STAMP_REPORT() do{ PrintTimeStampReport(); }while(0)
#else //ALIRO_MEASURE_PERFORMANCE
#define RESET_TIME_STAMP()
#define PRINT_TIME_STAMP(pos)
#define TIME_STAMP_REPORT()
#endif //ALIRO_MEASURE_PERFORMANCE
#define countof(_A_) (sizeof(_A_) / sizeof(*(_A_))) /**< Macro to count array elements */
#define PLATFORM_LOG(VERBOSITY, ...) do{if((uint8_t)VERBOSITY <= (uint8_t)nVerbosityLevel)LOG_INFO_APP(__VA_ARGS__);}while(0)
#define DELAY_CONDITIONAL(D) do{if( nVerbosityLevel > VERB_VERBOSE)HAL_Delay(D);}while(0)
#define HIGH_BYTE(A) ((A&0xFF00)>>8)
#define LOW_BYTE(A) (A&0x00FF)
#define HEX(C) (((C>='0') && (C<='9'))?(C-'0'):((C>='A') && (C<='F'))?(C-'A'+0xA):(0))
#define GET_IAR_YEAR_DEC(D) ((HEX(D[7])*1000 + HEX(D[8])*100 + HEX(D[9])*10 + HEX(D[10])*1) - 2000)
#define GET_IAR_YEAR(D) (GET_IAR_YEAR_DEC(D)%10 + (GET_IAR_YEAR_DEC(D)/10)*16 - 0x30)
#define GET_IAR_DATE(D) (HEX(D[4])*16 + HEX(D[5])*1)
#define GET_IAR_HOURS(T) (HEX(T[0])*16 + HEX(T[1])*1)
#define GET_IAR_MINUTES(T) (HEX(T[3])*16 + HEX(T[4])*1)
#define GET_IAR_SECONDS(T) (HEX(T[6])*16 + HEX(T[7])*1)
#define GET_IAR_MONTH(D) (\
(D[0]==JAN[0] && D[1] == JAN[1] && D[2] == JAN[2])?0x1:\
(D[0]==FEB[0] && D[1] == FEB[1] && D[2] == FEB[2])?0x2:\
(D[0]==MAR[0] && D[1] == MAR[1] && D[2] == MAR[2])?0x3:\
(D[0]==APR[0] && D[1] == APR[1] && D[2] == APR[2])?0x4:\
(D[0]==MAY[0] && D[1] == MAY[1] && D[2] == MAY[2])?0x5:\
(D[0]==JUN[0] && D[1] == JUN[1] && D[2] == JUN[2])?0x6:\
(D[0]==JUL[0] && D[1] == JUL[1] && D[2] == JUL[2])?0x7:\
(D[0]==AUG[0] && D[1] == AUG[1] && D[2] == AUG[2])?0x8:\
(D[0]==SEP[0] && D[1] == SEP[1] && D[2] == SEP[2])?0x9:\
(D[0]==OCT[0] && D[1] == OCT[1] && D[2] == OCT[2])?0x10:\
(D[0]==NOV[0] && D[1] == NOV[1] && D[2] == NOV[2])?0x11:\
(D[0]==DEC[0] && D[1] == DEC[1] && D[2] == DEC[2])?0x12:\
1)
#define TRANSACTION_SUCCESS_OPEN() AliroPort_TRANSACTION_SUCCESS_OPEN()
#define TRANSACTION_SUCCESS_CLOSE() AliroPort_TRANSACTION_SUCCESS_CLOSE()
#define TRANSACTION_FAILURE() AliroPort_TRANSACTION_FAILURE()
/**
* @}
*/
/** @addtogroup Aliro_app_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Returns the current timestamp.
* @return Timestamp value.
*/
uint32_t GetTimeStamp(void);
/**
* @brief Prints the timestamp associated with a string.
* @param pstr Descriptive string.
* @return Printed timestamp value.
*/
uint32_t PrintTimeStamp(char *pstr);
/**
* @brief Gets the current date and time.
* @param timeDate Pointer to struct tm to store the date and time.
*/
void GetTimeDate(struct tm *timeDate);
/**
* @brief Shows current date and time.
*/
void ShowTimeDate(void);
#if defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
/**
* @brief Sets the RTC configuration status.
* @param nStatus Status to set.
*/
void SetRtcSettingStatus(uint32_t nStatus);
#endif //defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
/**
* @brief Resets all saved timestamps.
*/
void ResetAllSavedTimeStamps(void);
/**
* @brief Searches for the position of a timestamp.
* @param pos Position to search.
* @return Pointer to the found statItem_t structure.
*/
statItem_t *SearchPos(timeStampsPos_t pos);
/**
* @brief Saves the timestamp in a specific position.
* @param pos Timestamp position.
*/
void SaveTimeStamp(timeStampsPos_t pos);
/**
* @brief Prints the timestamp report.
*/
void PrintTimeStampReport(void);
/**
* @brief Resets the current timestamp.
*/
void ResetTimeStamp(void);
/**
* @brief Prints a buffer in hexadecimal format.
* @param pstr Descriptive string.
* @param pBuf Buffer to print.
* @param nSize Buffer size.
*/
void PrintBufferHex(const char *pstr, const uint8_t *pBuf, const uint32_t nSize);
/**
* @brief Always prints a buffer in hexadecimal format.
* @param pstr Descriptive string.
* @param pBuf Buffer to print.
* @param nSize Buffer size.
*/
void PrintBufferHexAlways(const char *pstr, const uint8_t *pBuf, const uint32_t nSize);
/**
* @brief Prints an error string.
* @param errstr Error string.
* @param retval Return code.
*/
void PrintErrorString(char*errstr, ACWG_Status_t retval);
/**
* @brief Receives a character from USART.
* @param buf Buffer to store the character.
* @return Number of received characters.
*/
uint16_t UsartGetChar(uint8_t *buf);
/**
* @brief Receives a character from USART in blocking mode.
* @param buf Buffer to store the character.
* @return Number of received characters.
*/
uint16_t UsartGetCharBlocking(uint8_t *buf);
/**
* @brief Initializes the Aliro module.
* @return true if initialization is successful, false otherwise.
*/
bool aliro_init();
/**
* @brief Executes the main Aliro process.
*/
void aliro_process();
/**
* @brief Hook for successful transaction - Door open
*/
__weak void AliroPort_TRANSACTION_SUCCESS_OPEN(void);
/**
* @brief Hook for successful transaction - Door close
*/
__weak void AliroPort_TRANSACTION_SUCCESS_CLOSE(void);
/**
* @brief Hook for transaction failure
*/
__weak void AliroPort_TRANSACTION_FAILURE(void);
/**
* @brief Delay porting for Aliro.
* @param Delay Delay time in ms.
*/
void AliroPort_Delay(uint32_t Delay);
/**
* @brief Writes the state of a GPIO pin.
* @param GPIOx Pointer to GPIO.
* @param GPIO_Pin Pin to write.
* @param PinState State to set.
*/
void AliroPort_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
/**
* @brief Transmits data via UART.
* @param huart UART handle.
* @param pData Data to transmit.
* @param Size Data size.
* @param Timeout Operation timeout.
* @return HAL status.
*/
HAL_StatusTypeDef AliroPort_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout);
/**
* @brief Receives data via UART.
* @param huart UART handle.
* @param pData Data buffer.
* @param Size Pointer to data size.
* @param Timeout Operation timeout.
* @return HAL status.
*/
HAL_StatusTypeDef AliroPort_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t *Size, uint32_t Timeout);
/**
* @brief Interrupt Service Routine for button 1.
*/
void Button1_isr( void );
/**
* @brief Board reset.
*/
void board_reset();
/**
* @brief Checks if the selected SPSM is valid.
* @param selected Selected SPSM.
* @return 1 if valid, 0 otherwise.
*/
uint8_t isValidSPSM(uint16_t selected);
/**
* @brief Gets dynamic SPSM.
* @param old_spsm Previous SPSM.
* @return Dynamic SPSM.
*/
uint16_t get_dynamic_spsm(uint8_t old_spsm);
/**
* @brief Fills the advertising buffer.
* @param advbuf Advertising buffer.
* @param psize Pointer to size.
*/
void fillAdvBuffer(uint8_t *advbuf, uint8_t *psize);
/**
* @brief Gets the initial length of Aliro service parameters.
* @param pLen Pointer to length.
* @return Length.
*/
uint8_t AliroSvcParamGetInitLen(uint8_t *pLen);
/**
* @brief Gets the initial buffer of Aliro service parameters.
* @param DataBuf Pointer to data buffer.
* @return Buffer length.
*/
uint8_t AliroSvcParamGetInitBuf(uint8_t **DataBuf);
/**
* @brief Verifies the Aliro protocol version.
* @param selectedProtocolVersion_16 Selected version.
* @return 1 if valid, 0 otherwise.
*/
uint8_t AliroSvcVerifyProtVer(uint16_t selectedProtocolVersion_16);
/**
* @brief Gets the saved selected protocol version.
* @return Selected version.
*/
uint16_t AliroGetSavedSelectedProtocolVersion();
/**
* @brief BLE Aliro initialization complete callback.
*/
void AliroBLE_Init_complete_cb();
/**
* @brief BLE Aliro disconnection complete callback.
*/
void AliroBleDisconnection_complete_cb();
/**
* @brief BLE CoC Aliro disconnection complete callback.
*/
void AliroBleCocDisconnection_complete_cb();
/**
* @brief Fills techs2find for Aliro.
* @param techs2find Pointer to techs2find.
*/
void AliroFilltechs2Find(uint16_t *techs2find);
/**
* @brief Set the timeout for the prepare ranging operation.
*
* @param timeout_ms Timeout value in milliseconds.
*/
void Set_timeout_prepare_ranging(uint32_t timeout_ms);
/**
* @brief Set the timeout for the execute ranging operation.
*
* @param timeout_ms Timeout value in milliseconds.
*/
void Set_timeout_execute_ranging(uint32_t timeout_ms);
/**
* @brief Set the timeout for the suspend ranging operation.
*
* @param timeout_ms Timeout value in milliseconds.
*/
void Set_timeout_suspend_ranging(uint32_t timeout_ms);
/**
* @brief Set the timeout for the resume ranging operation.
*
* @param timeout_ms Timeout value in milliseconds.
*/
void Set_timeout_resume_ranging(uint32_t timeout_ms);
/**
* @brief Set the timeout for the door operation.
*
* @param timeout_ms Timeout value in milliseconds.
*/
void Set_timeout_door_operation(uint32_t timeout_ms);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _APP_ALIRO_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,100 @@
/**
******************************************************************************
* @file : app_build_info.h
* @brief : Header for app_build_info.c file.
* This file contains the firmware build information structure.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _APP_BUILD_INFO_H_
#define _APP_BUILD_INFO_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NFCBLE
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/** @addtogroup App_build_info_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @brief Current version of @ref app_build_info
*/
#define ABI_VERSION 1
/**
* @}
*/
/** @addtogroup App_build_info_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @brief Various info about the firmware build
*
* The build info are put at a specific address in flash (e.g. 0x0200), so that we can easily recover it with an
* external application which would read the flash.
*/
typedef struct app_build_info_s {
uint8_t magic_cookie[4]; //!< A magic cookie that external application could easily read: 'B', 'F', 'W', 'I'
uint8_t build_info_version; //!< Version of this structure, e.g. @ref MBI_VERSION
uint8_t app_major; //!< Major version number of the firmware
uint8_t app_minor; //!< Minor version number of the firmware
uint8_t app_subminor; //!< Subminor version number of the firmware
// char revision[32]; //!< git version at the build time, based on hash
char date[12]; //!< Build date, e.g. "Jan 1 1970"
char time[12]; //!< Build time, e.g. "01:00:00"
uint8_t aliro_spec_major; //!< Major version number of the Aliro spec.
uint8_t aliro_spec_minor; //!< Minor version number of the Aliro spec.
uint8_t aliro_spec_subminor; //!< Subminor version number of the Aliro spec.
uint8_t acwg_ver_major;
uint8_t acwg_ver_minor;
uint8_t acwg_ver_subminor;
#define MBI_FW_DESCRIPTION_LEN 24
char fw_description[MBI_FW_DESCRIPTION_LEN]; //!< Name of the firmware
}app_build_info_t;
/**
* @}
*/
/** @addtogroup App_build_info_Exported_Variables
* @{
*/
// The symbol 'build_info' is defined by the linker script. See file arm-gcc-link.ld
// Alternatively, we could use:
// #define build_info (*(struct buildinfo*)(0x08000200))
/* Exported variables ------------------------------------------------------------*/
extern const app_build_info_t app_build_info;
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _APP_BUILD_INFO_H_ */

View File

@@ -0,0 +1,108 @@
/**
******************************************************************************
* @file : app_nfc.h
* @brief : Header for app_nfc.c file.
* This file contains the public NFC API and common NFC definitions for the Aliro application.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _APP_NFC_H_
#define _APP_NFC_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NFC
* @{
*/
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include <stdbool.h>
#include "st_errno.h"
#include "ACWG_Security.h"
/** @addtogroup Aliro_NFC_ExportedTypes
* @brief Exported types for Aliro NFC module
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @} */
/** @addtogroup Aliro_NFC_ExportedConstants
* @brief Exported constants for Aliro NFC module
* @{
*/
/* Exported constants --------------------------------------------------------*/
/** @} */
/** @addtogroup Aliro_NFC_ExportedMacros
* @brief Exported macros for Aliro NFC module
* @{
*/
/* Exported macro ------------------------------------------------------------*/
/** @} */
/** @addtogroup Aliro_NFC_ExportedFunctions
* @brief Exported functions for Aliro NFC module
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initializes the NFC module for Aliro.
* @param context Pointer to the session context.
* @return true if initialization is successful, false otherwise.
*/
bool AliroNfcIni( ACWG_SessionContext_t *context );
/**
* @brief Executes the main NFC cycle for Aliro.
* @param context Pointer to the session context.
*/
void AliroNfcCycle( ACWG_SessionContext_t *context );
/**
* @brief Stops the NFC module for Aliro.
*/
void AliroNfcStop( void );
/**
* @brief Gets the technologies to find during NFC discovery.
* @return Bitmask of technologies to find.
*/
uint16_t AliroNfcGetDiscoverTechs2Find( void );
/**
* @brief Gets the total duration for NFC discovery.
* @return Duration in milliseconds.
*/
uint16_t AliroNfcGetDiscoverTotalDuration( void );
/**
* @brief Initializes the NFC hardware for Aliro.
*/
void AliroNfcHwInit( void );
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _APP_NFC_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file : app_version.h
* @brief : Header for app_version.c file.
* This file defines application and specification version macros used by the Aliro firmware.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _APP_VERSION_H_
#define _APP_VERSION_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NFCBLE
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "provisioning_info.h"
/** @addtogroup App_Version_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
#define APP_VERSION_MAJ 0
#define APP_VERSION_MIN 9
#define APP_VERSION_SUBMIN 3
// #define APP_VERSION "0.1.0"
// #define SW_VERSION "FW VERSION TBD"
#define ALIRO_SPEC_VERSION_MAJ 0
#define ALIRO_SPEC_VERSION_MIN 9
#define ALIRO_SPEC_VERSION_SUBMIN 5
#define APP_ACWG_VERSION_MAJ 0
#define APP_ACWG_VERSION_MIN 3
#define APP_ACWG_VERSION_SUBMIN 4
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _APP_VERSION_H_ */

View File

@@ -0,0 +1,238 @@
/**
******************************************************************************
* \file certificate.h
* \author STMicroelectronics - CS application team
* \brief x509 certificate Parser
******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2022 STMicroelectronics</center></h2>
*
* This software is licensed under terms that can be found in the LICENSE file in
* the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef CERTIFICATE_H
#define CERTIFICATE_H
#include <stdint.h>
/** \defgroup certificate_core Certificate parser
* \ingroup certificate
* \brief Certificate parser
* @{
*/
/**
* \enum certificate_status_t
* \brief response codes enumeration
*/
typedef enum {
CERT_OK = 0x00, /*!< Successful processing */
CERT_INVALID_PARAMETER = 0x01, /*!< Wrong function parameters */
CERT_UNEXPECTED_SEQUENCE,
CERT_UNEXPECTED_BITSTRING,
CERT_INVALID_SIGNATURE,
CERT_INVALID_CERTIFICATE,
CERT_CA_NOT_MATCHING,
CERT_UNSUPPORTED_FEATURE,
CERT_BAD_SIZE,
}certificate_status_t;
/** \brief Definitions of available signature algorithms */
typedef enum {
CERT_SIG_ECDSA_SHA1 = 0, /*!< ECDSA with SHA1 algorithm */
CERT_SIG_ECDSA_SHA224, /*!< ECDSA with SHA224 algorithm */
CERT_SIG_ECDSA_SHA256, /*!< ECDSA with SHA256 algorithm */
CERT_SIG_ECDSA_SHA384, /*!< ECDSA with SHA384 algorithm */
CERT_SIG_ECDSA_SHA512, /*!< ECDSA with SHA512 algorithm */
}certificate_signature_algorithms_t;
/** \brief Definitions of supported Elliptic Curve Names */
typedef enum {
CERT_EC_P256 = 0, /*!< NIST P-256 */
CERT_EC_P384, /*!< NIST P-384 */
CERT_EC_P521, /*!< NIST P-521 */
CERT_EC_bp256r1, /*!< brainpoolP256r1 */
CERT_EC_bp256t1, /*!< brainpoolP256t1 */
CERT_EC_bp384r1, /*!< brainpoolP384r1 */
CERT_EC_bp384t1, /*!< brainpoolP384t1 */
CERT_EC_bp512r1, /*!< brainpoolP512r1 */
CERT_EC_bp512t1, /*!< brainpoolP512t1 */
}certificate_elliptic_curves_t;
/** \brief typedef for the structure keeping the validity */
typedef struct validity_st {
uint8_t seconds; /*!< seconds (range 0 to 59) */
uint8_t minutes; /*!< minutes (range 0 to 59) */
uint8_t hours; /*!< hours (range 0 to 23) */
uint8_t days; /*!< days (range 1 to 31) */
uint8_t month; /*!< month (range 1 to 12) */
uint32_t year; /*!< years 0 to whatever */
} cert_validity_t;
/** \brief typedef for the structure keeping the Ellipitc Curve Public Key */
typedef struct cert_public_key_t
{
const uint8_t *pX; /*!< Pointer to X Coordinate */
const uint8_t *pY; /*!< Pointer to Y Coordiante */
uint32_t fsize; /*!< Size of the field in bytes */
} cert_public_key_t;
/** \brief typedef for the structure keeping the ECDSA Signature */
typedef struct ECDSAsign_st
{
const uint8_t *pR; /*!< Pointer to r */
uint32_t rSize; /*!< size to r */
const uint8_t *pS; /*!< Pointer to s*/
uint32_t sSize; /*!< size to s */
} cert_signature_t;
/** \brief internal structure used to keep the values parsed from the x509 */
struct internal_certificate {
const uint8_t *pPubKey_point_representation_id; /*!< 0x04: Uncompressed key, 0x02 or 0x03: Compressed key */
const uint8_t *tbs; /*!< Pointer to tcs field */
uint32_t tbsSize; /*!< Size of tcs */
uint32_t x509Version; /*!< x509 Version */
const uint8_t *serialNumber; /*!< Pointer to SerialNumber*/
uint32_t serialNumberSize; /*!< Size of SerialNumber */
uint32_t signature; /*!< Signature (algorithm) but from tcs */
const uint8_t *issuer; /*!< Pointer to Issuer */
uint32_t issuerSize; /*!< Size of Issuer */
const uint8_t *validity; /*!< Pointer to Validity */
uint32_t validitySize; /*!< Size of Validity */
const uint8_t *subject; /*!< Pointer to subject */
uint32_t subjectSize; /*!< Size of Subject */
uint32_t EllipticCurve; /*!< Identifies the Elliptic Curve */
cert_public_key_t PubKey; /*!< Contain the struct \ref cert_public_key_t */
const uint8_t *extensions; /*!< Pointer to Extensions */
uint32_t extensionsSize; /*!< Size of Extensions */
uint32_t extensionsFlags; /*!< Integer encoding the fields present in the tcs: \n
* bit 0: BasicConstraints is present \n
* bit 1: BasicConstraints is critical \n
* bit 2: BasicConstraints indicates this is a CA \n
* bit 3: BasicConstraints has a pathLenConstraint \n
* bit 4-7: PathLen \n
* bit 8: keyUsage is present \n
* bit 9: keyUsage is critical \n
* bit 15: keyUsage field decipherOnly \n
* bit 16: keyUsage field digitalSignature \n
* bit 17: keyUsage field contentCommitment/nonRepudiation \n
* bit 18: keyUsage field keyEncipherment \n
* bit 19: keyUsage field dataEncipherment \n
* bit 20: keyUsage field keyAgreement \n
* bit 21: keyUsage field keyCertSign \n
* bit 22: keyUsage field cRLSign \n
* bit 23: keyUsage field encipherOnly \n
* bit 24: ExtendedKeyUsage is present \n
* bit 25: ExtendedKeyUsage is critical \n
* bit 27-29: Unused
*/
const uint8_t *extAKIkeyIdentifier; /*!< field key identifier of extension authority key identifier */
uint32_t extAKIkeyIdentifierSize; /*!< size of previous field */
uint32_t SignatureAlgorithm; /*!< SignatureAlgorithm */
cert_signature_t Sign; /*!< Contain the struct \ref cert_signature_t */
};
/** \brief typedef for the certificate_t */
typedef struct internal_certificate certificate_t;
/* Exported Functions */
/**
* \brief Initialize a certificate (\ref certificate_t) to an empty one
* \param[in,out] cert pointer to the certificate_t to be initialized
* \note This functions should be called before parsing a certificate
* \details \include{doc} Authentication.dox
*/
void certificate_init(certificate_t *cert);
/**
* \brief Parse an x509 certificate
* \param[in] cert pointer to the x509 certificate to be parsed
* \param[in] max_size maximum size of certificate to be parsed
* \param[out] certificate pointer to the certificate_t that will be filled
* \param[out] next pointer to cert array after the parsed certificate (it can be NULL)
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
* \warning The parsed certificated could be empty, it is necessary to call a function
* which verifies the certificate to be valid before using it.
*/
certificate_status_t certificate_parse(const uint8_t *cert, uint32_t max_size, certificate_t *certificate, const uint8_t **next);
/**
* \brief Parse the top of x509 certificate to find the tbs and the signature
* \param[in] cert pointer to the x509 certificate to be parsed
* \param[in] max_size maximum size of certificate to be parsed
* \param[out] certificate pointer to the certificate_t that will be filled
* \param[out] next pointer to cert array after the parsed certificate (it can be NULL)
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
* \warning The parsed certificated could be empty, it is necessary to call a function
* which verifies the certificate to be valid before using it.
*/
certificate_status_t certificate_find_tbs_and_signature(const uint8_t *cert, uint32_t max_size, certificate_t *certificate, const uint8_t **next);
/**
* \brief Parse the tbs part of a certificate
* \param[in/out] *certificate pointer to the certificate_t
*/
void certificate_parse_tbs(certificate_t *certificate);
/**
* \brief Check that an imported x509 certificate is valid
* \param[in] certificate pointer to the parsed x509 certificate to be validated
* \param[in] currentTime pointer to a cert_validity_t with the current DateTime. If NULL no date check is done
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
* \warning If currentTime==NULL the check on the validity dates of the certificate will be bypassed.
*/
certificate_status_t certificate_is_valid(const certificate_t *certificate, const cert_validity_t *currentTime);
/**
* \brief Check whether a certificate is marked as belonging to a CA
* \param[in] *cert pointer to the parsed x509 certificate to be checked
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
*/
certificate_status_t certificate_is_CA(const certificate_t *cert);
/**
* \brief Check whether "parent" issued "child"
* \param[in] parent pointer to the parsed x509 certificate of the supposed issuer of child
* \param[in] child pointer to the parsed x509 certificate of the certificated supposedly issued by parent
* \param[in] currentTime pointer to a cert_validity_t with the current DateTime. If NULL no date check is done.
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
* \note RFC 5280 mandates an extremely expensive comparison, which we don't perform.
* As result of this simplification some legitimate parentship relation could be not acknowledged (the opposite should not occur).
* \warning This check only a single level parent relashion (i.e. whether parent issued child)
*/
certificate_status_t certificate_is_parent(const certificate_t *parent, const certificate_t *child, const cert_validity_t *currentTime);
/**
* \brief Copy a certificate (\ref certificate_t) into another structure
* \param[out] copiedCert pointer to the certificate_t that will be written
* \param[out] originalCert pointer to the certificate_t that will be copied
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
*/
void certificate_copy(certificate_t *copiedCert, const certificate_t *originalCert);
/**
* \brief Iterate over the certificate chain in argument and check each child/parent pairs
* \param[in] rootCA Pointer to the root CA certificate buffer
* \param[in] certChain Pointer to the certificate chain buffer
* \param[in] certChainSize Size of the certificate chain buffer
* \param[out] leafCert Pointer to the leaf certificate structure
* \return : ertificate_status_t 0 on success ; error code otherwise
*/
certificate_status_t certificate_parse_chain(
uint8_t *rootCA,
uint8_t *certChain,
uint16_t certChainSize,
certificate_t *leafCert);
/** @}*/
#endif /* CERTIFICATE_H */

View File

@@ -0,0 +1,69 @@
/**
******************************************************************************
* \file certificate_crypto.h
* \author STMicroelectronics - CS application team
* \brief Crypto functionalities for x509 verification
******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2022 STMicroelectronics</center></h2>
*
* This software is licensed under terms that can be found in the LICENSE file in
* the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef CERTIFICATE_CRYPTO_H
#define CERTIFICATE_CRYPTO_H
/** \defgroup certificate_crypto Certificate cryptography
* \ingroup certificate
* \brief Certificate cryptography functions
* @{
*/
/**
* \brief Verify the signature of a certificate with a public key
* \param[in] signing_public_key pointer to the parsed x509 certificate containing the public key to be used for the signature verification
* \param[in] signing_public_key_size size in bytes of the digest of the message to be verified
* \param[in] certificate pointer to the parsed x509 certificate to verify
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
*/
certificate_status_t certificate_verify_signature(const uint8_t* signing_public_key, uint32_t signing_public_key_size, const certificate_t* certificate);
#if 0
/**
* \brief Verify the signature of a digest with a public key extracted from the certificate
* \param[in] cert pointer to the parsed x509 certificate containing the public key to be used for the signature verification
* \param[in] digest the digest of the message to be verified
* \param[in] digestSize size in bytes of the digest of the message to be verified
* \param[in] signatureR the R value of the signature to be verified
* \param[in] signatureRsize the size in bytes of signatureR
* \param[in] signatureS the S value of the signature to be verified
* \param[in] signatureSsize the size in bytes of signatureS
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
*/
certificate_status_t certificate_verify_signature(
const certificate_t *cert,
const uint8_t *digest,
int32_t digestSize,
const uint8_t *signatureR,
int32_t signatureRsize,
const uint8_t *signatureS,
int32_t signatureSsize);
#endif
/**
* \brief Check whether "parent" signed "child"
* \param[in] parent pointer to the parsed x509 certificate of the supposed issuer of child
* \param[in] child pointer to the parsed x509 certificate of the certificated supposedly issued by parent
* \return \ref certificate_status_t : CERT_OK on success ; error code otherwise
*/
certificate_status_t certificate_verify_child_signature(
const certificate_t *parent,
const certificate_t *child);
/** @}*/
#endif /* CERTIFICATE_CRYPTO_H */

View File

@@ -0,0 +1,289 @@
/**
******************************************************************************
* \file certificate_subparsing.h
* \author STMicroelectronics - CS application team
* \brief Helper for the x509 certificate Parser
******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2022 STMicroelectronics</center></h2>
*
* This software is licensed under terms that can be found in the LICENSE file in
* the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef CERTIFICATE_SUBPARSING_H
#define CERTIFICATE_SUBPARSING_H
/** \defgroup certificate_subparsing Certificate subparsing routines
* \ingroup certificate
* \brief Certificate subparsing routines
* \{
*/
/** \brief Definitions of X509 TAGs */
typedef enum {
TAG_BOOLEAN = 0x01, /*!< x509 tag for BOOLEAN */
TAG_INTEGER, /*!< x509 tag for INTEGER */
TAG_BITSTRING, /*!< x509 tag for BITSTRING */
TAG_OCTETSTRING, /*!< x509 tag for OCTETSTRING */
TAG_NULL, /*!< x509 tag for NULL */
TAG_OBJECT_IDENTIFIER, /*!< x509 tag for OBJECT_IDENTIFIER */
TAG_ObjectDescriptor, /*!< x509 tag for ObjectDescriptor */
TAG_ENUMERATED = 0x0A, /*!< x509 tag for ENUMERATED */
TAG_UTF8String = 0x0C, /*!< x509 tag for UTF8String */
TAG_PrintableString = 0x13, /*!< x509 tag for PrintableString */
TAG_IA5String = 0x16, /*!< x509 tag for IA5String */
TAG_UTCTime, /*!< x509 tag for UTCTime */
TAG_GeneralizedTime, /*!< x509 tag for GeneralizedTime */
TAG_SEQUENCE = 0x30, /*!< x509 tag for SEQUENCE */
TAG_SET, /*!< x509 tag for SET */
TAG_OPTION_0 = 0x80, /*!< x509 tag for option 0 */
TAG_OPTION_1 , /*!< x509 tag for option 1 */
TAG_OPTION_2 , /*!< x509 tag for option 2 */
TAG_OPTION_3 , /*!< x509 tag for option 3 */
TAG_x509VERSION = 0xA0, /*!< x509 tag for x509VERSION */
TAG_issuerUniqueID, /*!< x509 tag for issuerUniqueID */
TAG_subjectUniqueID, /*!< x509 tag for subjectUniqueID */
TAG_extensions, /*!< x509 tag for extensions */
}certificate_tag_t;
/** \brief Definitions of supported Name Attributes */
typedef enum {
ATTR_CN = 3, /*!< CommonName */
ATTR_SN = 5, /*!< SerialNumber */
ATTR_C = 6, /*!< Country */
ATTR_LN = 7, /*!< LocalityName */
ATTR_SOPN = 8, /*!< stateOrProvinceName */
ATTR_ON = 10, /*!< Organization Name */
ATTR_OUN = 11, /*!< Organization Unit Name */
ATTR_UID = 45, /*!< UniqueIdentifier */
ATTR_DN = 49, /*!< DistinguishedName */
}certificate_name_attributes_t;
/** \brief Definitions of supported Extensions types */
typedef enum {
EXTENSION_KU = 15, /*!< KeyUsage */
EXTENSION_BC = 19, /*!< BasicContrains */
EXTENSION_AKI = 35, /*!< authority key identifier */
EXTENSION_EKU = 37, /*!< extKeyUsage */
}certificate_extensions_type_t;
/** \brief Structure used to keep SignatureAlgorithm OIDs */
struct SignatureAlgorithmOID_st
{
uint32_t len; /*!< size of the encoded OID */
uint32_t type; /*!< type of OID */
uint8_t oid[8]; /*!< encoded OID */
};
/** \brief Structure used to keep Name Attribute OIDs */
struct AttributeOID_st
{
uint32_t len; /*!< size of the encoded OID */
uint32_t type; /*!< type of OID */
uint8_t oid[3]; /*!< encoded OID */
};
/** \brief Structure used to keep named Elliptic Curve OIDs */
struct EllipticCurveOID_st
{
uint32_t len; /*!< size of the encoded OID */
uint32_t type; /*!< type of OID */
uint8_t oid[9]; /*!< encoded OID */
};
/** \brief typedef for the attribute */
typedef struct attribute_st
{
uint32_t type; /*!< type of attribute (corresponding to OID) */
uint32_t strFormat; /*!< format of the string */
const uint8_t *str; /*!< pointer to the string of the attribute */
uint32_t strSize; /*!< size of the string */
} cert_attribute_t;
/** \brief Structure used to keep Name Attribute OIDs */
struct ExtensionOID_st
{
uint32_t len; /*!< size of the encoded OID */
uint32_t type; /*!< type of OID */
uint8_t oid[5]; /*!< encoded OID */
};
/** \brief typedef for the extension */
typedef struct extension_st
{
uint32_t type; /*!< type of extension (corresponding to OID) */
uint32_t critical; /*!< critical */
const uint8_t *value;/*!< pointer to the value hold by the extension (this is an octet string) */
uint32_t valueSize; /*!< size of the string */
} cert_extension_t;
/* Exported Macros */
/** \brief Macro which checks if a TAG is valid (known) */
#define IS_VALID_TAG(tag) (( \
(TAG_BOOLEAN <= (tag) && (tag) <= TAG_ObjectDescriptor) || \
(tag) == TAG_ENUMERATED || \
(tag) == TAG_UTF8String || \
(tag) == TAG_PrintableString || \
(TAG_IA5String <= (tag) && (tag) <= TAG_GeneralizedTime) || \
(tag) == TAG_SEQUENCE || \
(tag) == TAG_SET || \
(TAG_OPTION_0 <= (tag) && (tag) <= TAG_OPTION_3) || \
(TAG_x509VERSION <= (tag) && (tag) <= TAG_extensions) ) ? 1 : 0)
/**
* \brief Identify the ASN.1 TLV
* \param[in] *asn1 pointer to the ASN.1 TLV
* \param[out] *parsed will contain the number of processed bytes (rarely used)
* \param[out] *size will contain the size (in bytes) of the value field of this ASN.1 TLV
* \param[out] **value will contain a pointer to the value field of this ASN.1 TLV
* \param[in/out] *max_size maximum size left for value
* \return The internal TAG identifier of this TLV or -1 if failure
*/
int32_t certificate_identify_ASN1_TLV(const uint8_t *asn1, int32_t *parsed, int32_t *size, const uint8_t **value, uint32_t* max_size);
/**
* \brief Identify the Name Attribute from its OID
* \param[in] *oid The value of the OID of the Attribute (got from \ref certificate_identify_ASN1_TLV )
* \param[in] size size (in bytes) of the value field of this OID (got from \ref certificate_identify_ASN1_TLV )
* \note Only a very limited set of Attributes is supported
* \return The internal type identifing the Attribute or -1 for failure
*/
int32_t certificate_identify_attribute(const uint8_t *oid, int32_t size);
/**
* \brief Parse an ECDSA signature
* \param[in] *signature pointer to the expected signature field of the x509 certificate
* \param[out] *certificate pointer to the certificate_t that will be filled
* \param[out] **next_thing will contain a pointer to the next TLV
*/
void certificate_parse_ECDSA_signature(const uint8_t *signature, certificate_t *certificate, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse the x509 Version of a certificate
* \param[in] *x509VersionField pointer to the version field of a certificate
* \param[out] *certificate pointer to the certificate_t that will be filled
* \param[out] **next_thing output pointer to next TLV
*/
void certificate_parse_X509_version(const uint8_t *x509VersionField, certificate_t *certificate, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse a SignatureAlgorithm (or signature of a tbsCertificate)
* \param[in] *SA pointer to the SignatureAlgorithm (or signature of a tbsCertificate)
* \param[out] *singatureAlgorithm integer that will be filled with the internal encoding of signatureAlgorithm
* \param[out] **next_thing output pointer to next TLV
* \note Only a very limited set of SignatureAlgorithm is supported
*/
void certificate_parse_signature_algorithm(const uint8_t *SA, uint32_t *singatureAlgorithm, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse an ECC public Key from a certificate
* \param[in] *EccPK pointer to the ECC public Key
* \param[out] *certificate pointer to the certificate_t that will be filled
* \param[out] **next_thing output pointer to next TLV
*/
void certificate_parse_ECC_public_key(const uint8_t *EccPK, certificate_t *certificate, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse an ASN.1 INTEGER
* \param[in] *integer pointer to the expected INTEGER TLV
* \param[out] *outp will point to the starting byte of the integer
* \param[out] *outSize will contain the size of the integer in bytes
* \param[out] **next_thing will contain a pointer to the next TLV
* \note This doesn't copy the integer. To keep memory small this just returns a pointer to it.
* \warning only non-negative integers are supported
*/
void certificate_parse_integer(const uint8_t *integer, const uint8_t **outp, uint32_t *outSize, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse the validity of a certificate
* \param[in] *p pointer to the Name Attribute SET to be parsed
* \param[out] *notBefore_st pointer to cert_validity_t structure that will be filled with the "not before" date
* \param[out] *notAfter_st pointer to cert_validity_t structure that will be filled with the "not after" date
* \param[out] **next_thing output pointer to next TLV
* \note In this function next_thing can be NULL
*/
void certificate_parse_validity(const uint8_t *p, cert_validity_t *notBefore_st, cert_validity_t *notAfter_st, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Parse an RelativeDistinguishedName
* \param[in] *p pointer to the RelativeDistinguishedName (expeting a SET)
* \param[out] **nextRDN output pointer to next RDN
* \param[out] **attribute output pointer to RDN first attribute
*/
void certificate_parse_relative_distinguished_name(const uint8_t *p, const uint8_t **nextRDN, const uint8_t **attribute, uint32_t* max_size);
/**
* \brief Parse a Name Attribute
* \param[in] *p pointer to the AttributeTypeAndValue SEQUENCE to be parsed
* \param[out] *attribute_st pointer to cert_attribute_t structure that will be filled
* \param[out] **next_thing output pointer to next TLV
*/
void certificate_parse_attribute(const uint8_t *p, cert_attribute_t *attribute_st, const uint8_t **next_thing, uint32_t* max_size);
/**
* \brief Compare two cert_validity_t structures
* \param[in] *D1 pointer to the first cert_validity_t
* \param[in] *D2 pointer to the second cert_validity_t
* \return Result of Comparison
* \retval -1 D1 < D2
* \retval 0 D1 = D2
* \retval 1 D1 > D2
*/
int32_t certificate_date_compare(const cert_validity_t *D1, const cert_validity_t *D2);
/**
* \brief Count the number of Attributes within a NAME
* \param[in] *p pointer to the RDNSequence to be parsed
* \returun The number of Attributes
*/
int32_t certificate_count_attributes(const uint8_t *p);
/**
* \brief String Comparison (case insensitive and for utf8)
* \param[in] *p1 first string to compare
* \param[in] *p2 second string to compare
* \param[in] size p1/p2 size
* \return result of comparison
* \retval -1 strings are different
* \retval 0 strings match
*/
int32_t certificate_case_insensitive_compare(const uint8_t *p1, const uint8_t *p2, int32_t size);
/**
* \brief Identify the Extension from its OID
* \param[in] *oid The value of the OID of the Extension (got from \ref certificate_identify_ASN1_TLV )
* \param[in] size size (in bytes) of the value field of this OID (got from \ref certificate_identify_ASN1_TLV )
* \note Only a very limited set of Extension is supported
* \return The internal type identifing the Extension or -1 for failure
*/
int32_t certificate_case_identify_extension(const uint8_t *oid, int32_t size);
/**
* \brief Parse an x509 Extension
* \param[in] *ext pointer to the extension
* \param[out] certificate structure
* \param[out] *ext_st pointer to an cert_extension_t structure
*/
void certificate_parse_extension(const uint8_t *ext, certificate_t *certificate, cert_extension_t *ext_st, uint32_t* max_size);
/**
* \brief Reads the value of an INTEGER and returns it as a int32_t
* \param[in] *value pointer to the value field of an INTEGER TLV (got from \ref certificate_identify_ASN1_TLV)
* \param[in] size size of the integer (got from \ref certificate_identify_ASN1_TLV)
* \return the integer value as an int32_t
* \warning only non-negative integers are supported
*/
int32_t certificate_get_small_integer(const uint8_t *value, int32_t size);
/** \}*/
#endif /* CERTIFICATE_SUBPARSING_H */

View File

@@ -0,0 +1,236 @@
/**
******************************************************************************
* @file : custom_uwb.h
* @brief : Header for custom_uwb.c file.
* This file contains the public declarations for the custom UWB functions.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _CUSTOM_UWB_H_
#define _CUSTOM_UWB_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "ACWG_Security.h"
/** @addtogroup BLE_UWB
* @{
*/
/** @addtogroup UWB_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initialize UWB session.
* Uses for UWB Context and ranging session initialization.
* @param ctx Session context.
*/
void Initiate_uwb_ctx(ACWG_SessionContext_t *ctx);
/**
* @brief Handle UWB time synchronization frame.
* Uses to process and apply time sync information for the current UWB session.
* @param ctx Session context.
*/
void Handle_uwb_Time_Sync(ACWG_SessionContext_t *ctx);
/**
* @brief Fill outbound M1 message fields.
* Uses to fill UWB M1 message fields:
* The first three fields depends of the UWB capabilities.
* 1. UWB Configuration Identifier
* 2. Pulse Shape Combination
* 3. Channel Bitmask
* 4. UWB Session Identifier
* 5. Vendor Specific attribute is optionally present.
* @param ctx Session context.
*/
void Fill_uwb_M1(ACWG_SessionContext_t *ctx);
/**
* @brief Handle inbound M2 message fields.
* Uses to handle UWB M2 message fields:
* The first three fields is linked to the same in M1 and represents the device selection,
* then the follow fields are session parameters/mask available by device:
* 1. UWB Configuration Identifier
* 2. Pulse Shape Combination
* 3. Channel Bitmask
* 4. SYNC Code Index Bitmask
* 5. RAN Multiplier
* 6. Slot Bitmask
* 7. Hopping Configuration Bitmask
* 8. Vendor Specific attribute is optionally present.
* @param ctx Session context.
*/
void Handle_uwb_M2(ACWG_SessionContext_t *ctx);
/**
* @brief Fill outbound M3 message fields.
* Uses to fill UWB M3 message fields:
* The follow fields are session parameters set by the Reader based on M2 content:
* 1. RAN Multiplier
* 2. Number Chaps per Slot
* 3. Number Responders Nodes
* 4. Number Slots per Round
* 5. SYNC Code Index Bitmask
* 6. Hopping Configuration Bitmask
* 7. MAC Mode
* 8. Vendor Specific attribute is optionally present.
* @param ctx Session context.
*/
void Fill_uwb_M3(ACWG_SessionContext_t *ctx);
/**
* @brief Handle inbound M4 message fields.
* Uses to handle UWB M4 message fields.
* The follow fields are session parameters set by the device based on M3 content:
* 1. STS Index0
* 2. UWB Time0
* 3. HOP Mode Key
* 4. SYNC Code Index
* 5. Vendor Specific attribute is optionally present.
* @param ctx Session context.
*/
void Handle_uwb_M4(ACWG_SessionContext_t *ctx);
/**
* @brief Prepare the ranging initialization step.
* Called only once after M1/M2/M3/M4 exchange.
* @param ctx Session context.
*/
void Prepare_ranging_init(ACWG_SessionContext_t *ctx);
/**
* @brief Prepare the ranging loop step.
* Called repeatedly in the prepare ranging loop until timeout expires.
* Uses to setup uwb ranging parameters before starting ranging.
* @param ctx Session context.
* @param timeout Pointer to timeout in ms. Set to 1 to exit the loop.
*/
void Prepare_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout);
/**
* @brief Execute the ranging initialization step.
* Called only one time after prepare ranging steps.
* Uses to start the UWB ranging .
* @param ctx Session context.
*/
void Execute_ranging_init(ACWG_SessionContext_t *ctx);
/**
* @brief Execute the ranging loop step.
* Called repeatedly in the execute ranging loop until timeout expires.
* Uses to perform UWB ranging acquisition and evaluate ranging results.
* Exiting this loop the Handle_lock_actuation function is called.
* @param ctx Session context.
* @param timeout Pointer to timeout in ms. Set to 1 to exit the loop.
*/
void Execute_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout);
/**
* @brief Close the ranging initialization step.
* Called only one time after Handle_lock_actuation.
* Uses to stop and deinit UWB ranging session.
* @param ctx Session context.
*/
void Close_ranging_init(ACWG_SessionContext_t *ctx);
/**
* @brief Close the ranging loop step.
* Called repeatedly in the close ranging loop until timeout expires.
* @param ctx Session context.
* @param timeout Pointer to timeout in ms. Set to 1 to exit the loop.
*/
void Close_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout);
/**
* @brief Suspend the ranging initialization step.
* Called only one time after suspend response or suspend event in ranging session.
* Uses to stop UWB ranging session.
* @param ctx Session context.
*/
void Suspend_ranging_init(ACWG_SessionContext_t *ctx);
/**
* @brief Suspend the ranging loop step.
* Called repeatedly in the suspend ranging loop until timeout expires.
* @param ctx Session context.
* @param timeout Pointer to timeout in ms. Set to 1 to exit the loop.
*/
void Suspend_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout);
/**
* @brief Resume the ranging initialization step.
* Called only one time after resume response in ranging session.
* Uses to set new Time0 and SlotIndex0 in UWB ranging session.
* @param ctx Session context.
*/
void Resume_ranging_init(ACWG_SessionContext_t *ctx);
/**
* @brief Resume the ranging loop step.
* Called repeatedly in the resume ranging loop until timeout expires.
* After exiting this loop the Execute_ranging_init function is called.
* @param ctx Session context.
* @param timeout Pointer to timeout in ms. Set to 1 to exit the loop.
*/
void Resume_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout);
/**
* @brief Handle and evaluate distance results.
* Called only one time during preparing Reader Status Exchange frame.
* Uses to notify if distance allowed to open the lock.
* @param ctx Session context.
* @return 1 if distance allowed to open lock, 0 otherwise.
*/
uint8_t Handle_distance_result(ACWG_SessionContext_t *ctx);
/**
* @brief Trigger lock actuation based on session state.
* Called only one time after Execute_ranging_loop.
* Uses to actuate the lock based on distance result evaluation.
* @param ctx Session context.
*/
void Handle_lock_actuation(ACWG_SessionContext_t *ctx);
/**
* @brief Initialize UWB hardware.
* Uses for UWB hardware initialization, called only one time at startup.
*/
void UWB_HW_init( void );
/**
* @brief Run periodic UWB hardware tasks.
* Uses for periodic UWB hardware tasks, called repeatedly in main loop.
*/
void UWB_HW_loop( void );
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _CUSTOM_UWB_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,99 @@
/**
******************************************************************************
* @file : flash_mng.h
* @brief : Header for flash_mng.c file.
* This file declares the Flash management API used by the Aliro application (erase/write helpers).
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _FLASH_MNG_H_
#define _FLASH_MNG_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup FLASH_MNG
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "app_nfc.h"
//#include "utils.h"
#include "main.h"
/** @addtogroup Flash_mng_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @enum flashOpStatus_e
* @brief Status codes for flash operations.
*/
typedef enum _flashOpStatus
{
FLASH_OP_OK, /**< Operation successful */
FLASH_OP_BUSY, /**< Flash is busy */
FLASH_OP_ERROR /**< Operation failed */
}
flashOpStatus_e;
/**
* @}
*/
/** @addtogroup Flash_mng_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Writes data to flash memory.
* @param data Pointer to the data to write.
* @param nBytes Number of bytes to write.
* @param nAddress Destination address in flash.
* @return Status of the operation.
*/
flashOpStatus_e WriteToFlash(void *data, uint32_t nBytes, uint32_t nAddress);
/**
* @brief Erases the flash sector and writes data to it.
* @param data Pointer to the data to write.
* @param nBytes Number of bytes to write.
* @param nAddress Destination address in flash.
* @return Status of the operation.
*/
flashOpStatus_e EraseWriteToFlash(void *data, uint32_t nBytes, uint32_t nAddress);
/**
* @brief Erases a region of flash memory.
* @param nAddress Start address of the region to erase.
* @param nBytes Number of bytes to erase.
* @return Status of the operation.
*/
flashOpStatus_e EraseFlash(uint32_t nAddress, uint32_t nBytes);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _FLASH_MNG_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,73 @@
/**
******************************************************************************
* @file : log_module_u5.h
* @brief : Header for log_module_u5.c file.
* Provides logging macros and prototypes for the U5 platform.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LOG_MODULE_U5_H_
#define _LOG_MODULE_U5_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "st_errno.h"
/** @addtogroup NFCBLE
* @{
*/
/** @addtogroup log_module_u5_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
typedef uint8_t Log_Verbose_Level_t;
typedef uint8_t Log_Region_t;
/**
* @}
*/
/** @addtogroup log_module_u5_Exported_Macros
* @{
*/
/* Exported macro ------------------------------------------------------------*/
/**
* @def LOG_INFO_APP
* @brief Macro for logging information messages in the application.
* @param ... Arguments to be printed using DBG_PRINTF.
*/
#define LOG_INFO_APP(...) do{Log_Module_Print(0,0,__VA_ARGS__);}while(0)
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _LOG_MODULE_U5_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,73 @@
/**
******************************************************************************
* @file : log_module_u5.h
* @brief : Header for log_module_u5.c file.
* Provides logging macros and prototypes for the U5 platform.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _LOG_MODULE_U5_H_
#define _LOG_MODULE_U5_H_
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "st_errno.h"
/** @addtogroup NFCBLE
* @{
*/
/** @addtogroup log_module_u5_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
typedef uint8_t Log_Verbose_Level_t;
typedef uint8_t Log_Region_t;
/**
* @}
*/
/** @addtogroup log_module_u5_Exported_Macros
* @{
*/
/* Exported macro ------------------------------------------------------------*/
/**
* @def LOG_INFO_APP
* @brief Macro for logging information messages in the application.
* @param ... Arguments to be printed using DBG_PRINTF.
*/
#define LOG_INFO_APP(...) do{Log_Module_Print(0,0,__VA_ARGS__);}while(0)
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _LOG_MODULE_U5_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,284 @@
/**
******************************************************************************
* @file : provisioning.h
* @brief : Header for provisioning module.
* This file contains the common defines and structures for provisioning.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef _PROVISIONING_H_
#define _PROVISIONING_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup PROVISIONING_MNG
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "ACWG_Security.h"
#include "stdbool.h"
#include "provisioning_info.h"
/** @addtogroup Provisioning_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @def PRIVATE_KEY_SIZE_BYTES
* @brief Size of private key in bytes.
*/
#define PRIVATE_KEY_SIZE_BYTES ((uint32_t)32)
/**
* @def AUTH_PUBKEY_LEN_BYTES
* @brief Length of authentication public key in bytes.
*/
#define AUTH_PUBKEY_LEN_BYTES ((uint32_t)64)
/**
* @def GROUP_RESOLVING_KEY_SIZE_BYTES
* @brief Size of group resolving key in bytes.
*/
#define GROUP_RESOLVING_KEY_SIZE_BYTES ((uint32_t)16)
/**
* @def DEVICE_NAME_SIZE_BYTES
* @brief Size of device name in bytes.
*/
#define DEVICE_NAME_SIZE_BYTES ((uint32_t)16)
/**
* @def B1_VENDOR_SPEC_EXT_SIZE_BYTES
* @brief Size of vendor specific extension in bytes.
*/
#define B1_VENDOR_SPEC_EXT_SIZE_BYTES ((uint32_t)64)
/**
* @def RESERVED_PAIRING_KEYS_SIZE_BYTES
* @brief Size of buffer in bytes reserved for future use .
*/
#define RESERVED_PAIRING_KEYS_SIZE_BYTES ((uint32_t)32)
/**
* @def CERTIFICATE_SIZE
* @brief Size of certificate data in bytes.
*/
#define CERTIFICATE_SIZE ((uint32_t)400)
/**
* @def NUM_PROV_DEVICES
* @brief Maximum number of provisioned devices.
*/
#define NUM_PROV_DEVICES 5
/**
* @}
*/
/** @addtogroup Provisioning_Exported_Variables
* @{
*/
/* Exported variables ------------------------------------------------------------*/
/**
* @}
*/
/** @addtogroup Provisioning_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @struct devices_t
* @brief Structure representing a provisioned device.
*/
typedef struct devices_s
{
uint8_t name[DEVICE_NAME_SIZE_BYTES]; /**< Device name */
uint8_t endpoint_Keyslot[AUTH_KEYSLOT_LEN_BYTES]; /**< Endpoint keyslot */
uint8_t endpoint_PubK[AUTH_PUBKEY_LEN_BYTES]; /**< Endpoint public key */
uint8_t endpoint_PrivK[PRIVATE_KEY_SIZE_BYTES]; /**< Endpoint private key */
}devices_t;
/**
* @struct provstruct_t
* @brief Structure representing the provisioning data.
*/
typedef struct provstruct_s
{
uint32_t isValid; /**< Validity flag */
uint8_t readerID[AUTH_READER_GROUP_ID_LEN_BYTES + AUTH_READER_GROUP_SUB_ID_LEN_BYTES]; /**< Reader ID */
uint8_t readerPubK[AUTH_PUBKEY_LEN_BYTES]; /**< Reader public key */
uint8_t staticPrivateKey[PRIVATE_KEY_SIZE_BYTES]; /**< Static private key */
uint8_t group_resolving_key[GROUP_RESOLVING_KEY_SIZE_BYTES]; /**< Group resolving key */
uint8_t certificate_data[CERTIFICATE_SIZE]; /**< Certificate data */
uint32_t certificate_len; /**< Certificate length */
uint8_t readerIssuerPubK[AUTH_PUBKEY_LEN_BYTES]; /**< Reader issuer public key */
uint8_t b1VendorSpecificExtension[B1_VENDOR_SPEC_EXT_SIZE_BYTES]; /**< Vendor specific extension */
uint32_t b1VendorSpecificExtensionLen; /**< Vendor specific extension length */
uint32_t numDevices; /**< Number of devices */
devices_t devices[NUM_PROV_DEVICES]; /**< Array of provisioned devices */
uint32_t isValidReserved; /**< RESERVED validity flag */
uint8_t reservedPairingKeys[RESERVED_PAIRING_KEYS_SIZE_BYTES]; /**< RESERVED pairing keys */
uint32_t struct_size; /**< Structure size */
}provstruct_t;
/**
* @}
*/
/** @addtogroup Provisioning_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Shows the status of the JSON provisioning data.
*/
void showJsonStatus();
/**
* @brief Shows the status of the provisioning data.
*/
void showProvisioningStatus();
/**
* @brief Saves the provisioning data to flash memory.
* @param profile_num Profile number to save.
*/
void saveProvisioningToFlash(uint32_t profile_num);
/**
* @brief Retrieves the provisioning data from flash memory.
* @return Pointer to the provisioning structure.
*/
provstruct_t* getProvisioningFromFlash();
/**
* @brief Loads provisioning data from a JSON address.
* @param jsonAddress Address of the JSON data.
* @param provstruct Pointer to the provisioning structure to fill.
*/
void loadProvisionFromJson(uint32_t jsonAddress, provstruct_t*provstruct);
/**
* @brief Converts provisioning data from JSON format.
* @param jsonAddress Address of the JSON data.
*/
void convertProvisioningFromJson(uint32_t jsonAddress);
/**
* @brief Converts default provisioning data from JSON format.
*/
void convertDefaultProvisioningFromJson();
/**
* @brief Prints the device JSON data.
*/
void printDeviceJson();
/**
* @brief Prints the script JSON data.
*/
void printScriptJson();
/**
* @brief Saves the reader public key to flash memory.
* @param pkey Pointer to the public key.
* @param ksize Size of the key.
*/
void saveRDPubKToFlash(const uint8_t *pkey, const uint8_t ksize);
/**
* @brief Saves the reader private key to flash memory.
* @param pkey Pointer to the private key.
* @param ksize Size of the key.
*/
void saveRDPrvKToFlash(const uint8_t *pkey, const uint8_t ksize);
/**
* @brief Saves the reader identity to flash memory.
* @param pkey Pointer to the identity data.
* @param ksize Size of the identity data.
*/
void saveRDidenToFlash(const uint8_t *pkey, const uint8_t ksize);
/**
* @brief Saves the reader group resolving key to flash memory.
* @param pkey Pointer to the group resolving key.
* @param ksize Size of the key.
*/
void saveRDgrrkToFlash(const uint8_t *pkey, const uint8_t ksize);
/**
* @brief Saves the credential issuer public key to flash memory.
* @param pkey Pointer to the credential issuer public key.
* @param ksize Size of the public key.
*/
void saveCredIsPkToFlash(const uint8_t *pkey, const uint8_t ksize);
/**
* @brief Saves the access credential public key.
* @param last_pkey Pointer to the last public key.
* @param ksize Size of the key.
* @param nSlot Slot number.
*/
void saveAccessCredentialPuBK(uint8_t *pkey, const uint8_t ksize, uint8_t nSlot, uint8_t *pkeyname);
/**
* @brief Checks if a buffer contains only zeros.
* @param pBuf Pointer to the buffer.
* @param nSize Size of the buffer.
* @return 1 if all zeros, 0 otherwise.
*/
uint8_t is_zeros(uint8_t* pBuf, uint32_t nSize);
/**
* @brief Checks the endpoint public key for provisioning.
* @param endp_PubK Pointer to the endpoint public key.
* @return Status code.
*/
uint8_t ProvisioningCheckEndpointPubK(uint8_t *endp_PubK);
/**
* @brief Gets the endpoint public key from a keyslot.
* @param endp_PubK Pointer to the endpoint public key.
* @param endp_Keyslot Pointer to the endpoint keyslot.
* @param slotFound Pointer to the found slot.
* @return Status code.
*/
uint8_t ProvisioningGetEndpointPubKFromKeyslot(uint8_t *endp_PubK, uint8_t *endp_Keyslot, uint8_t*slotFound);
/**
* @brief Converts a hex string to a hex buffer.
* @param p Pointer to the hex string.
* @param len Length of the string.
* @param hexp Pointer to the hex buffer.
*/
void hexStrToHex(char *p, uint32_t len, uint8_t *hexp);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif //_PROVISIONING_H_
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,157 @@
/**
******************************************************************************
* @file : provisioning_info.h
* @brief : Provisioning information and configuration defines for the application.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _PROVISIONING_INFO_H_
#define _PROVISIONING_INFO_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup PROVISIONING_MNG
* @{
*/
/** @addtogroup Provisioning_info_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @def ALIRO_APP_NAME
* @brief Application name string.
*/
#define ALIRO_APP_NAME "TruELock"
/**
* @def DEFAULT_CMD_PARAMS_VALUE
* @brief Default command parameters value (0 = Standard, 1 = Fast).
*/
#define DEFAULT_CMD_PARAMS_VALUE 0
/**
* @def NFC_PROP_BUF_CONTENT
* @brief Default NFC property buffer content.
*/
#define NFC_PROP_BUF_CONTENT { 0 }
/**
* @def BLE_ADV_DISABLE
* @brief Disable BLE advertising (0 = enabled).
*/
#define BLE_ADV_DISABLE 0
/**
* @def ALIRO_NFC_TOTAL_DURATION
* @brief Total duration for NFC operations in milliseconds.
*/
#define ALIRO_NFC_TOTAL_DURATION 1000U
/**
* @def TEST_HARNESS_SIMULATION
* @brief Enable test harness simulation (0 = disabled).
*/
#define TEST_HARNESS_SIMULATION 0
/**
* @def ALIRO_PROT_VER
* @brief Defines the default Aliro protocol versions supported for authentication and transport.
*/
#define ALIRO_PROT_VER_DEFAULT ( AUTH_EXP_TRANS_PROT_VERSION )
/**
* @def ALIRO_PROT_VER
* @brief Defines the Aliro protocol versions supported for authentication and transport.
*/
#define ALIRO_PROT_VER xProtocolVersionSupported
/**
* @def ALIRO_MAIN_PROT_VER
* @brief Main protocol version (lower 16 bits).
*/
#define ALIRO_MAIN_PROT_VER (ALIRO_PROT_VER & 0xffff)
/**
* @def ALIRO_HAS_SEC_PROT_VER
* @brief Check if secondary protocol version is present.
*/
#define ALIRO_HAS_SEC_PROT_VER ((ALIRO_PROT_VER&0xFFFF0000)?(1):(0))
/**
* @def ALIRO_SEC_PROT_VER
* @brief Secondary protocol version (upper 16 bits).
*/
#define ALIRO_SEC_PROT_VER ((ALIRO_PROT_VER&0xFFFF0000)>>16)
/**
* @def DEVICE_PROVISIONING_STRUCT_IS_VALID
* @brief Magic value indicating a valid device provisioning structure.
*/
#define DEVICE_PROVISIONING_STRUCT_IS_VALID 0xA5A55A5A
/**
* @def EXPIRY_TIME_STAMP_DEFAULT_VALUE
* @brief Default expiry timestamp value.
*/
#define EXPIRY_TIME_STAMP_DEFAULT_VALUE 0x76100fe0
/** @} */ // end of Provisioning_info_Constants
/** @addtogroup Provisioning_info_Macros
* @{
*/
/* Exported macro ------------------------------------------------------------*/
/**
* @def DISPLAY_SPLASH
* @brief Macro to display splash screen.
*/
#define DISPLAY_SPLASH()
/**
* @def LOAD_NFC_PROP
* @brief Macro to load NFC properties.
*/
#define LOAD_NFC_PROP()
/**
* @def DET_NFC_PROP
* @brief Macro to detect NFC properties.
*/
#define DET_NFC_PROP()
/**
* @def INIT_NFC_PROP
* @brief Macro to initialize NFC properties.
*/
#define INIT_NFC_PROP()
/**
* @def UWB_SESSION_ID_DEFAULT
* @brief Default UWB session ID value.
*/
#define UWB_SESSION_ID_DEFAULT getUwbSessionId()
/** @} */ // end of Provisioning_info_Macros
/** @addtogroup Provisioning_info_Includes
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "User_provisioning.h"
/** @} */ // end of Provisioning_info_Includes
/** @} */ // end of PROVISIONING
#ifdef __cplusplus
}
#endif
#endif //_PROVISIONING_INFO_H_
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,249 @@
/**
******************************************************************************
* @file : sm_crypto.h
* @brief : Header for sm_crypto.c file.
* This file provides the interface for SM cryptographic operations.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _SM_CRYPTO_H_
#define _SM_CRYPTO_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup MCU_CRYPTO
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/** @addtogroup SM_Crypto_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @def RAW_PRIV_KEY_BYTE_SIZE
* @brief Size of raw private key in bytes.
*/
#define RAW_PRIV_KEY_BYTE_SIZE ((uint32_t)32)
/**
* @def SHA256_BYTE_SIZE
* @brief Size of SHA-256 hash in bytes.
*/
#define SHA256_BYTE_SIZE ((uint32_t)32)
/**
* @def ECDSA_256_SIG_BYTE_SIZE
* @brief Size of ECDSA-256 signature in bytes.
*/
#define ECDSA_256_SIG_BYTE_SIZE ((uint32_t)64)
/**
* @}
*/
/** @addtogroup SM_Crypto_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @enum SM_Crypto_Error_t
* @brief Error codes for SM cryptographic operations.
*/
typedef enum {
SM_Crypto_OK = 0, /**< Operation successful */
SM_Crypto_Error, /**< General error */
SM_Crypto_HW_Error /**< Hardware error */
} SM_Crypto_Error_t;
/**
* @}
*/
/** @addtogroup SM_Crypto_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initializes the cryptographic module.
* @return Error code.
*/
SM_Crypto_Error_t SM_init(void);
/**
* @brief Generates random bytes.
* @param bytes Pointer to output buffer.
* @param size Number of bytes to generate.
* @return Error code.
*/
SM_Crypto_Error_t SM_genRandomBytes(uint8_t *bytes, uint32_t size);
/**
* @brief Generates a keypair and returns the public key.
* @param pub Pointer to output public key buffer.
* @return Error code.
*/
SM_Crypto_Error_t SM_genKeypair(uint8_t *pub);
/**
* @brief Key Derivation Function RFC5869.
* @param pZ Input keying material.
* @param ZSize Size of input keying material.
* @param pSalt Pointer to salt.
* @param saltSize Size of salt.
* @param pFixedInfo Pointer to fixed info.
* @param fixedInfoSize Size of fixed info.
* @param L Length of output keying material.
* @param pOutput Pointer to output buffer.
* @return Error code.
*/
SM_Crypto_Error_t SM_KDFRFC5869(const uint8_t* pZ, uint32_t ZSize,
const uint8_t* pSalt, uint32_t saltSize,
const uint8_t* pFixedInfo, uint32_t fixedInfoSize,
uint32_t L, uint8_t* pOutput);
/**
* @brief Computes SHA-1 hash.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @param hash Pointer to output hash buffer.
* @return Error code.
*/
SM_Crypto_Error_t SM_sha1(uint8_t *input, uint32_t inputSize, uint8_t *hash);
/**
* @brief Computes SHA-256 hash.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @param hash Pointer to output hash buffer.
* @return Error code.
*/
SM_Crypto_Error_t SM_sha256(uint8_t *input, uint32_t inputSize, uint8_t *hash);
/**
* @brief Starts SHA-256 computation.
* @return Error code.
*/
SM_Crypto_Error_t SM_sha256_start(void);
/**
* @brief Updates SHA-256 computation with new data.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @return Error code.
*/
SM_Crypto_Error_t SM_sha256_update(const uint8_t *input, uint32_t inputSize);
/**
* @brief Finishes SHA-256 computation and returns the hash.
* @param hash Pointer to output hash buffer.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @return Error code.
*/
SM_Crypto_Error_t SM_sha256_finish(uint8_t *hash, const uint8_t *input, uint32_t inputSize);
/**
* @brief Signs data using ECDSA.
* @param tbs Pointer to data to be signed.
* @param tbsSize Size of data to be signed.
* @param signature Pointer to output signature buffer.
* @return Error code.
*/
SM_Crypto_Error_t SM_sign(const uint8_t *tbs, uint32_t tbsSize, uint8_t *signature);
/**
* @brief Performs ECDH key agreement.
* @param pPublicKey Pointer to public key.
* @param pSharedSecret Pointer to output shared secret.
* @return Error code.
*/
SM_Crypto_Error_t SM_Ecdh(const uint8_t *pPublicKey, uint8_t *pSharedSecret);
/**
* @brief Derives KDH key.
* @param pZ Pointer to input keying material.
* @param info Pointer to info data.
* @param infoSize Size of info data.
* @param pKdh Pointer to output KDH key.
* @return Error code.
*/
SM_Crypto_Error_t SM_deriveKdh(const uint8_t *pZ, const uint8_t * info, uint32_t infoSize, uint8_t *pKdh);
/**
* @brief Decrypts data using AES-256 GCM.
* @param pKey Pointer to key.
* @param pNonce Pointer to nonce.
* @param pAad Pointer to additional authenticated data.
* @param aadSize Size of AAD.
* @param pPayload Pointer to encrypted payload.
* @param payloadSize Size of payload.
* @param pPlaintext Pointer to output plaintext buffer.
* @param pTag Pointer to authentication tag.
* @return Error code.
*/
SM_Crypto_Error_t SM_aes256GcmDecrypt(const uint8_t* pKey, const uint8_t* pNonce, const uint8_t* pAad, const uint32_t aadSize,
const uint8_t* pPayload, const uint32_t payloadSize, uint8_t* pPlaintext, const uint8_t* pTag);
/**
* @brief Encrypts data using AES-256 GCM.
* @param pKey Pointer to key.
* @param pNonce Pointer to nonce.
* @param pAad Pointer to additional authenticated data.
* @param aadSize Size of AAD.
* @param pInput Pointer to input data.
* @param inputSize Size of input data.
* @param pOutput Pointer to output buffer.
* @param pOutputSize Pointer to output size.
* @return Error code.
*/
SM_Crypto_Error_t SM_aes256GcmEncrypt(const uint8_t* pKey, const uint8_t* pNonce, const uint8_t* pAad, const uint32_t aadSize,
const uint8_t* pInput, const uint32_t inputSize, uint8_t* pOutput, uint32_t* pOutputSize);
/**
* @brief Verifies a signature using ECDSA.
* @param pPublicKey Pointer to public key.
* @param tbs Pointer to data to be verified.
* @param tbsSize Size of data to be verified.
* @param signature Pointer to signature.
* @return Error code.
*/
SM_Crypto_Error_t SM_verify(const uint8_t *pPublicKey, const uint8_t *tbs, const uint32_t tbsSize, const uint8_t *signature);
/**
* @brief Gets the certificate.
* @param certificate Pointer to output certificate buffer.
* @param certificateSize Pointer to output certificate size.
* @return Error code.
*/
SM_Crypto_Error_t SM_getCertificate(uint8_t *certificate, uint32_t *certificateSize);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif // _SM_CRYPTO_H_

View File

@@ -0,0 +1,79 @@
/**
******************************************************************************
* @file : sm_crypto_mcu.h
* @brief : Header for sm_crypto_mcu.c file.
* This file provides the interface for SM cryptographic operations on MCU platforms.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _SM_CRYPTO_MCU_H_
#define _SM_CRYPTO_MCU_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup MCU_CRYPTO
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "sm_crypto.h"
#if defined(STM32U545xx) || defined(STM32U585xx)
#include "stm32u5xx_hal.h"
#elif defined(STM32U385xx)
#include "stm32u3xx_hal.h"
#elif defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
#include "stm32wbaxx_hal.h"
#else
#error "product not supported"
#endif
/** @addtogroup SM_crypto_mcu_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @def MAX_FIXED_INFO_SIZE
* @brief Maximum size for fixed info buffer in bytes.
*/
#define MAX_FIXED_INFO_SIZE ((uint32_t)256)
/** @} */
/** @addtogroup SM_crypto_mcu_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initializes cryptographic hardware modules for MCU.
* @param rng Pointer to RNG handle.
* @param pka Pointer to PKA handle.
* @param hash Pointer to HASH handle.
* @param cryp Pointer to CRYP handle.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_initCryptoMCU(RNG_HandleTypeDef *rng, PKA_HandleTypeDef *pka, HASH_HandleTypeDef *hash, CRYP_HandleTypeDef *cryp);
/** @} */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif // _SM_CRYPTO_MCU_H_
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,67 @@
/**
******************************************************************************
* @file : sm_crypto_stsafe.h
* @brief : Header for sm_crypto_stsafe.c file.
* This file provides the interface for SM cryptographic operations using STSAFE.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _SM_CRYPTO_STSAFE_H_
#define _SM_CRYPTO_STSAFE_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup MCU_CRYPTO
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "sm_crypto.h"
#if defined(STM32U585xx)
#include "stm32u5xx_hal.h"
#elif defined(STM32WBA52xx) || defined(STM32WBA65xx)
#include "stm32wbaxx_hal.h"
#else
#error "product not supported"
#endif
#include "stselib.h"
/** @addtogroup SM_crypto_stsafe_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initializes cryptographic operations using STSAFE.
* @param pairingdone Pointer to a flag indicating if pairing is done.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_initCryptoStSafe(uint8_t *pairingdone);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif // _SM_CRYPTO_STSAFE_H_
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,122 @@
/**
******************************************************************************
* @file : stepup_mgr.h
* @brief : Header for stepup_mgr.c file.
* This file declares the interface for the step-up manager functionality.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STEPUP_MGR_H
#define __STEPUP_MGR_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup STEPUP_CORE
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "ACWG_Security.h"
#include "stdbool.h"
/** @addtogroup STEPUP_MGR_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
//typedef struct _access_mngr_data
//{
// uint8_t access_credential_PuBK_last[64];
//}
//access_mngr_data_t;
//
//extern access_mngr_data_t access_mngr_data;
/**
* @}
*/
/** @addtogroup STEPUP_MGR_Exported_Constants
* @{
*/
/* Exported constants --------------------------------------------------------*/
/**
* @}
*/
/** @addtogroup STEPUP_MGR_Exported_Macros
* @{
*/
/* Exported macro ------------------------------------------------------------*/
/**
* @}
*/
/** @addtogroup STEPUP_MGR_Private_Defines
* @{
*/
/* Private defines -----------------------------------------------------------*/
/**
* @}
*/
/** @addtogroup STEPUP_MGR_Exported_Functions
* @{
*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Requests a step-up operation.
* @param acwgctx Pointer to the session context.
* @param buf Pointer to the buffer for request data.
* @param len Pointer to the length of the buffer.
* @return Status code.
*/
uint8_t stepup_request(ACWG_SessionContext_t *acwgctx, uint8_t *stringAccElem, uint32_t AccElemLen, uint8_t *stringRevElem, uint32_t RevElemLen, uint8_t *buf, uint32_t *len);
/**
* @brief Pushes step-up data to the buffer.
* @param buf Pointer to the data buffer.
* @param len Length of the data.
* @return Status code.
*/
uint8_t stepup_pushdata(uint8_t *buf, uint32_t len);
/**
* @brief Processes the step-up operation.
* @param acwgctx Pointer to the session context.
* @return Status code.
*/
uint8_t stepup_process(ACWG_SessionContext_t *acwgctx);
/**
* @brief Checks the endpoint public key for step-up.
* @param endp_PubK Pointer to the endpoint public key.
* @return Status code.
*/
uint8_t stepup_CheckEndpointPubK(uint8_t *endp_PubK);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __STEPUP_MGR_H */

View File

@@ -0,0 +1,101 @@
/**
******************************************************************************
* @file : tlv.h
* @brief : Header for TLV (Tag-Length-Value) utilities.
* This file contains type definitions and function
* prototypes for TLV operations.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _TLV_H_
#define _TLV_H_
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup TLV_UTILITIES
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/** @addtogroup TLV_Utilities_Exported_Types
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @struct tlv_t
* @brief Structure representing a TLV (Tag-Length-Value) element.
*/
typedef struct {
uint8_t tag; /**< Tag identifier */
uint8_t *value; /**< Pointer to value data */
uint32_t length; /**< Length of value data */
} tlv_t;
/**
* @enum tlvStatus_t
* @brief Status codes for TLV operations.
*/
typedef enum {
TLV_SUCCESS, /**< Operation successful */
TLV_ERROR_SHORT_PAYLOAD, /**< Payload too short */
TLV_ERROR_INVALID_LENGTH, /**< Invalid length */
TLV_ERROR_SHORT_BUFFER, /**< Buffer too short */
TLV_ERROR_TAG_NOT_FOUND /**< Tag not found */
} tlvStatus_t;
/**
* @}
*/
/** @addtogroup TLV_Utilities_Exported_Functions
* @{
*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Extracts one TLV element from a buffer.
* @param tlvBuf Pointer to the buffer pointer.
* @param tlvLength Pointer to the buffer length.
* @param tlv Pointer to the TLV structure to fill.
* @return Status code.
*/
tlvStatus_t getOneTlv(uint8_t **tlvBuf, uint32_t *tlvLength, tlv_t *tlv);
/**
* @brief Appends a TLV element to a buffer.
* @param inputBuffer Pointer to the buffer pointer.
* @param inputBufferLen Pointer to the buffer length.
* @param tlv Pointer to the TLV structure to append.
* @return Status code.
*/
tlvStatus_t appendTLV(uint8_t **inputBuffer, uint32_t *inputBufferLen, const tlv_t *tlv);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _TLV_H_ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,550 @@
/**
******************************************************************************
* @file : tlwrapper.h
* @brief : Header for tlwrapper.c file.
* This file contains the type definitions and function
* prototypes for the tlwrapper module.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TLWRAPPER_H
#define __TLWRAPPER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "ACWG_Security.h"
#include "stdbool.h"
#include "custom_uwb.h"
/* Exported types ------------------------------------------------------------*/
/** @addtogroup WRAPPER_UTILITY
* @{
*/
/** @addtogroup TLWrapper_Utils_Exported_Types
* @{
*/
/**
* @enum tlw_error_e
* @brief Error codes for TLWrapper operations.
*/
typedef enum _tlw_error
{
TLW_ERROR_NONE = 0, /**< No error */
TLW_NEW_OUTPUT, /**< New output available */
TLW_NO_PREPARE_NEEDED, /**< No preparation needed */
TLW_ERROR_FAST, /**< Fast error */
TLW_NEED_GET_RESPONSE, /**< Need to get response */
TLW_NEED_AUTH1, /**< Need authentication 1 */
TLW_NEED_LOAD_CERT, /**< Need to load certificate */
TLW_BUSY, /**< Busy state */
TLW_FAIL_GENERATE, /**< Generation failed */
TLW_FAIL_PROCESS, /**< Processing failed */
TLW_FAIL_GENERIC, /**< Generic failure */
TLW_FAIL_TIMEOUT, /**< Timeout failure */
TLW_END /**< End of error codes */
}
tlw_error_e;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup NFC
* @{
*/
/** @addtogroup TLWrapper_Nfc_Exported_Types
* @{
*/
/**
* @enum tlw_state_nfc_e
* @brief NFC state machine states for TLWrapper.
*/
typedef enum _tlw_state_nfc
{
TLW_STATE_NFC_PREPARE_SELECT = 0,
TLW_STATE_NFC_PROCESS_SELECT,
TLW_STATE_NFC_PREPARE_AUTH0,
TLW_STATE_NFC_PROCESS_AUTH0,
TLW_STATE_NFC_PREPARE_LOAD_CERT,
TLW_STATE_NFC_PROCESS_LOAD_CERT,
TLW_STATE_NFC_PREPARE_AUTH1,
TLW_STATE_NFC_PROCESS_AUTH1,
TLW_STATE_NFC_PREPARE_AUTH1_CHAINED,
TLW_STATE_NFC_PROCESS_AUTH1_CHAINED,
TLW_STATE_NFC_PREPARE_SELECT_STEPUP,
TLW_STATE_NFC_PROCESS_SELECT_STEPUP,
TLW_STATE_NFC_PREPARE_STEPUP,
TLW_STATE_NFC_PROCESS_STEPUP,
TLW_STATE_NFC_PREPARE_GET_RESPONSE,
TLW_STATE_NFC_PREPARE_EXCHANGE,
TLW_STATE_NFC_PROCESS_EXCHANGE,
TLW_STATE_NFC_PREPARE_CONTROL_FLOW,
TLW_STATE_NFC_PROCESS_CONTROL_FLOW,
TLW_STATE_NFC_PREPARE_READER_STATUS_EXCHANGE,
TLW_STATE_NFC_PROCESS_READER_STATUS_EXCHANGE,
TLW_STATE_NFC_ERROR,
TLW_STATE_NFC_END
}
tlw_state_nfc_e;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup BLE_UWB
* @{
*/
/** @addtogroup TLWrapper_BleUwb_Exported_Types
* @{
*/
/**
* @enum tlw_state_ble_e
* @brief BLE state machine states for TLWrapper.
*/
typedef enum _tlw_state_ble
{
TLW_STATE_BLE_PREPARE_SELECT = 0,
TLW_STATE_BLE_PROCESS_SELECT,
TLW_STATE_BLE_PREPARE_AUTH0,
TLW_STATE_BLE_PROCESS_AUTH0,
TLW_STATE_BLE_PREPARE_LOAD_CERT,
TLW_STATE_BLE_PROCESS_LOAD_CERT,
TLW_STATE_BLE_PREPARE_AUTH1,
TLW_STATE_BLE_PROCESS_AUTH1,
TLW_STATE_BLE_PREPARE_STEPUP,
TLW_STATE_BLE_PROCESS_STEPUP,
TLW_STATE_BLE_PREPARE_GET_RESPONSE,
TLW_STATE_BLE_PREPARE_EXCHANGE,
TLW_STATE_BLE_PROCESS_EXCHANGE,
TLW_STATE_BLE_PREPARE_AP_COMPLETED,
TLW_STATE_BLE_PROCESS_AP_COMPLETED,
TLW_STATE_BLE_PROCESS_TIME_SYNC,
TLW_STATE_BLE_PROCESS_INITIATE_RANGING_SESSION,
TLW_STATE_BLE_PREPARE_M1,
TLW_STATE_BLE_PROCESS_M2,
TLW_STATE_BLE_PREPARE_M3,
TLW_STATE_BLE_PROCESS_M4,
// Reader initiated suspension
TLW_STATE_BLE_PREPARE_SUSPEND_RQU,
TLW_STATE_BLE_PROCESS_SUSPEND_RSP,
// Device initiated suspension
TLW_STATE_BLE_PREPARE_SUSPEND_RSP,
TLW_STATE_BLE_PROCESS_SUSPEND,
// Reader impose suspension
TLW_STATE_BLE_PREPARE_EVENT_RANGING_SUSPENDED,
// Device impose suspension
TLW_STATE_BLE_PROCESS_EVENT_RANGING_SUSPENDED,
// Device trigger resumption
TLW_STATE_BLE_PROCESS_EVENT_RANGING_RESUME,
TLW_STATE_BLE_PROCESS_RESUME_RSP,
TLW_STATE_BLE_PREPARE_RANGING,
TLW_STATE_BLE_EXECUTE_RANGING,
TLW_STATE_BLE_HANDLE_SUSPEND,
TLW_STATE_BLE_HANDLE_RESUME,
// Reader initiated resumption
TLW_STATE_BLE_PREPARE_RESUME_RQU,
TLW_STATE_BLE_HANDLE_DOOR_LOCK_OPERATION,
TLW_STATE_BLE_PREPARE_READER_STATUS_EXCHANGE,
TLW_STATE_BLE_PROCESS_READER_STATUS_EXCHANGE,
TLW_STATE_BLE_PREPARE_NOTIFICATION_EVENT_ERR,
TLW_STATE_BLE_ERROR,
TLW_STATE_BLE_END
}
tlw_state_ble_e;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup NFC
* @{
*/
/** @addtogroup TLWrapper_Nfc_Exported_Types
* @{
*/
/**
* @struct tlw_SM_nfc_t
* @brief Structure for NFC state machine context in TLWrapper.
*/
typedef struct _tlwrapper_SM_nfc
{
uint8_t flags_nfc;
tlw_state_nfc_e state;
ACWG_SessionContext_t *ctx;
uint8_t *input;
uint16_t *input_len;
uint8_t output[512];
uint16_t output_len;
ACWG_Status_t (*callback)(ACWG_SessionContext_t *ctx);
}
tlw_SM_nfc_t;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup WRAPPER_UTILITY
* @{
*/
/** @addtogroup TLWrapper_Utils_Exported_Types
* @{
*/
/**
* @enum General_Error_Attribute_ID_e
* @brief General error attribute IDs for BLE operations.
*/
typedef enum _General_Error_Attribute_ID
{
GENERAL_UNKNOWN_ERROR = 0U,
GENERAL_RESOURCE_UNAVAILABLE = 1U,
GENERAL_WRONG_PARAMETERS = 2U,
GENERAL_URSK_UNAVAILABLE = 3U
}
General_Error_Attribute_ID_e;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup BLE_UWB
* @{
*/
/** @addtogroup TLWrapper_BleUwb_Exported_Types
* @{
*/
/**
* @struct tlw_SM_ble_t
* @brief Structure for BLE state machine context in TLWrapper.
*/
typedef struct _tlwrapper_SM_ble
{
bool isBleOnly;
General_Error_Attribute_ID_e general_error_ble;
uint8_t flags_ble;
tlw_state_ble_e state;
ACWG_SessionContext_t *ctx;
uint8_t *input;
uint16_t *input_len;
uint8_t output[300];
uint16_t output_len;
ACWG_Status_t (*callback)(ACWG_SessionContext_t *ctx);
uint8_t (*sendData)(uint8_t *buff, uint16_t len);
uint8_t (*disconnect)(void);
}
tlw_SM_ble_t;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup WRAPPER_UTILITY
* @{
*/
/** @addtogroup TLWrapper_Utils_Exported_Types
* @{
*/
/**
* @struct access_mngr_data_t
* @brief Structure for access manager data.
*/
typedef struct _access_mngr_data
{
uint8_t access_credential_PuBK_last[64];
}
access_mngr_data_t;
/**
* @}
*/
/**
* @}
*/
/* Exported variables --------------------------------------------------------*/
/** @addtogroup NFC
* @{
*/
/** @addtogroup TLWrapper_Nfc_Exported_Variables
* @{
*/
/**
* @brief Global NFC state machine context.
*/
extern tlw_SM_nfc_t nfc_SM;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup BLE_UWB
* @{
*/
/** @addtogroup TLWrapper_BleUwb_Exported_Variables
* @{
*/
/**
* @brief Global BLE state machine context.
*/
extern tlw_SM_ble_t ble_SM;
/**
* @}
*/
/**
* @}
*/
/** @addtogroup WRAPPER_UTILITY
* @{
*/
/** @addtogroup TLWrapper_Utils_Exported_Variables
* @{
*/
/**
* @brief Global access manager data.
*/
extern access_mngr_data_t access_mngr_data;
/**
* @}
*/
/**
* @}
*/
/* Exported functions prototypes ---------------------------------------------*/
/** @addtogroup NFC
* @{
*/
/** @addtogroup TLWrapper_Nfc_Exported_Functions
* @{
*/
/**
* @brief Initializes the NFC state machine.
* @param ctx Pointer to session context.
* @return Error code.
*/
tlw_error_e tlw_init_nfc(ACWG_SessionContext_t *ctx);
/**
* @brief Reloads the NFC state machine.
* @param ctx Pointer to session context.
* @return Error code.
*/
tlw_error_e tlw_reload_nfc(ACWG_SessionContext_t *ctx);
/**
* @brief Prepares the NFC state machine for operation.
* @return Error code.
*/
tlw_error_e tlw_prepare_nfc(void);
/**
* @brief Processes the NFC state machine.
* @return Error code.
*/
tlw_error_e tlw_process_nfc(void);
/**
* @}
*/
/**
* @}
*/
/** @addtogroup BLE_UWB
* @{
*/
/** @addtogroup TLWrapper_BleUwb_Exported_Functions
* @{
*/
/**
* @brief Initializes the BLE state machine.
* @param ctx Pointer to session context.
* @return Error code.
*/
tlw_error_e tlw_init_ble(ACWG_SessionContext_t *ctx);
/**
* @brief Reloads the BLE state machine.
* @param ctx Pointer to session context.
* @return Error code.
*/
tlw_error_e tlw_reload_ble(ACWG_SessionContext_t *ctx);
/**
* @brief Prepares the BLE state machine for operation.
* @return Error code.
*/
tlw_error_e tlw_prepare_ble(void);
/**
* @brief Processes the BLE state machine.
* @return Error code.
*/
tlw_error_e tlw_process_ble(void);
/**
* @brief Handles received BLE data and sends response.
* @param data Pointer to received data buffer.
* @param len Pointer to length of received data.
* @param sendData_fn Function pointer to send data.
* @return Error code.
*/
tlw_error_e tlw_ble_receivedData(uint8_t *data, uint8_t *len, uint8_t (*sendData_fn)(uint8_t *, uint16_t));
/**
* @brief Steps the BLE state machine.
* @return Error code.
*/
tlw_error_e tlw_ble_SM_step(void);
/**
* @brief Gets the current UWB session ID.
* @return UWB session ID value.
*/
uint32_t getUwbSessionId( void );
/**
* @}
*/
/**
* @}
*/
/** @addtogroup WRAPPER_UTILITY
* @{
*/
/** @addtogroup TLWrapper_Utils_Exported_Functions
* @{
*/
/**
* @brief Checks the endpoint public key.
* @param endpointPub Pointer to context that contains endpoint public key.
* @return Status code.
*/
uint8_t tlw_CheckEndpointKey(ACWG_SessionContext_t *ctx);
/**
* @brief Gets the last endpoint public key.
* @return Pointer to the last endpoint public key.
*/
uint8_t* tlw_GetLastEndpointKey(void);
/**
* @brief Sets the access element string.
* @param AccElmStr Pointer to the access element string.
*/
void tlw_SetAccessElementString(uint8_t *AccElmStr);
/**
* @brief Gets the access element string.
* @return Pointer to the access element string.
*/
uint8_t *tlw_GetAccessElementString(void);
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __TLWRAPPER_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
#include "custom_uwb.h"
#include "main.h"
#include "app_aliro.h"
#define NUM_ITEMS 2
#define DISTANCE_OPEN 40
#define DEFAULT_FAR_DISTANCE 1000
#define TIME_CHECK_RANGING 5000
uint32_t nMeasures[NUM_ITEMS] = {0};
uint32_t mean_dist_cm = 0;
void responderReset(void)
{
for(uint32_t i=0;i<NUM_ITEMS;i++)nMeasures[i]=1000;
mean_dist_cm = DEFAULT_FAR_DISTANCE;
}
void Initiate_uwb_ctx(ACWG_SessionContext_t *ctx)
{
// responderReset();
// HAL_Delay(10);
// send_frame(...);
}
void Fill_uwb_M1(ACWG_SessionContext_t *ctx)
{
// UNUSED( ctx );
// force UWB Configuration Identifier to 0x0001
uint8_t AliroUWB_Configuration_Identifier[] = { 0x00, 0x00 };
memcpy(ctx->uwb_ctx.UWB_Configuration_Identifier, AliroUWB_Configuration_Identifier, sizeof(AliroUWB_Configuration_Identifier));
memcpy(ctx->uwb_ctx.UWB_Session_Identifier, &ctx->transId[12], 4);
// force pulse shape combo to 0x01
ctx->uwb_ctx.Pulse_Shape_Combo = 0x01;
// force channel bitmask to 0x01 (channel 5)
ctx->uwb_ctx.Channel_Bitmask = 0x01;
ctx->uwb_ctx.RAN_Multiplier = 0x02;
ctx->uwb_ctx.Number_Chaps_per_Slot = 0x0C;
ctx->uwb_ctx.Number_Responders_Nodes = 0x01;
ctx->uwb_ctx.Number_Slots_per_Round = 6;
ctx->uwb_ctx.MAC_Mode = 0x00;
}
void Fill_uwb_M3(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
uint8_t SYNC_Code_Index_Btmsk[SYNC_CODE_INDEX_BITMASK_LEN_BYTES] = {0x00, 0x00, 0x0F, 0x00};
memcpy(ctx->uwb_ctx.SYNC_Code_Index_Bitmask, SYNC_Code_Index_Btmsk, SYNC_CODE_INDEX_BITMASK_LEN_BYTES);
}
void Handle_uwb_M2(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Handle_uwb_M4(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Prepare_ranging_init(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Prepare_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout)
{
// if(configurationComplete())
// {
// *timeout = 1;//set timeout to a low value to exit loop in the main function
// }
}
static uint32_t nTimeoutCheckRanging = 0;
void Execute_ranging_init(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
nTimeoutCheckRanging = HAL_GetTick() + TIME_CHECK_RANGING;
//TODO: send start session command
}
void Execute_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout)
{
UNUSED( ctx );
static uint8_t is_ranging_validate = 0;
//TODO: process mean_dist_cm
if ((!is_ranging_validate) && (mean_dist_cm == DEFAULT_FAR_DISTANCE))
{
if (HAL_GetTick() > nTimeoutCheckRanging)
{
*timeout = 2;
}
}
else
{
is_ranging_validate = 1;
}
if(mean_dist_cm < DISTANCE_OPEN)
{
*timeout = 1;
}
}
void Close_ranging_init(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Close_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout)
{
UNUSED( ctx );
//TODO: send stop and deinit session commands
{
*timeout = 1;//set timeout to a low value to exit loop in the main function
}
}
void Suspend_ranging_init(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Suspend_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout)
{
UNUSED( ctx );
//TODO: send stop and deinit session commands
*timeout = 1;//set timeout to a low value to exit loop in the main function
}
void Resume_ranging_init(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
}
void Resume_ranging_loop(ACWG_SessionContext_t *ctx, uint32_t *timeout)
{
UNUSED( ctx );
*timeout = 1;//set timeout to a low value to exit loop in the main function
}
uint8_t Handle_distance_result(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
if(mean_dist_cm < DISTANCE_OPEN)
{
return 1;
}
else
{
return 0;
}
}
void Handle_lock_actuation(ACWG_SessionContext_t *ctx)
{
UNUSED( ctx );
PLATFORM_LOG(VERB_VERBOSE, "\r\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Distance MEAN: %u cm\r\n\n", mean_dist_cm);
if(mean_dist_cm < DISTANCE_OPEN)
{
PLATFORM_LOG(VERB_VERBOSE, "OPEN\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OOOOOOOOO PPPPPPPPPPPPPPPPP EEEEEEEEEEEEEEEEEEEEEENNNNNNNN NNNNNNNN\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OO:::::::::OO P::::::::::::::::P E::::::::::::::::::::EN:::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OO:::::::::::::OO P::::::PPPPPP:::::P E::::::::::::::::::::EN::::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::::OOO:::::::OPP:::::P P:::::PEE::::::EEEEEEEEE::::EN:::::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O::::::O O::::::O P::::P P:::::P E:::::E EEEEEEN::::::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P::::P P:::::P E:::::E N:::::::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P::::PPPPPP:::::P E::::::EEEEEEEEEE N:::::::N::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P:::::::::::::PP E:::::::::::::::E N::::::N N::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P::::PPPPPPPPP E:::::::::::::::E N::::::N N::::N:::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P::::P E::::::EEEEEEEEEE N::::::N N:::::::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::O O:::::O P::::P E:::::E N::::::N N::::::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O::::::O O::::::O P::::P E:::::E EEEEEEN::::::N N:::::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "O:::::::OOO:::::::OPP::::::PP EE::::::EEEEEEEE:::::EN::::::N N::::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OO:::::::::::::OO P::::::::P E::::::::::::::::::::EN::::::N N:::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OO:::::::::OO P::::::::P E::::::::::::::::::::EN::::::N N::::::N\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " OOOOOOOOO PPPPPPPPPP EEEEEEEEEEEEEEEEEEEEEENNNNNNNN NNNNNNN\r\n");
AliroPort_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
}
else
{
PLATFORM_LOG(VERB_VERBOSE, "CLOSE\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CCCCCCCCCCCCCLLLLLLLLLLL OOOOOOOOO SSSSSSSSSSSSSSS EEEEEEEEEEEEEEEEEEEEEE\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CCC::::::::::::CL:::::::::L OO:::::::::OO SS:::::::::::::::SE::::::::::::::::::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CC:::::::::::::::CL:::::::::L OO:::::::::::::OO S:::::SSSSSS::::::SE::::::::::::::::::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " C:::::CCCCCCCC::::CLL:::::::LL O:::::::OOO:::::::OS:::::S SSSSSSSEE::::::EEEEEEEEE::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " C:::::C CCCCCC L:::::L O::::::O O::::::OS:::::S E:::::E EEEEEE\r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::OS:::::S E:::::E \r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::O S::::SSSS E::::::EEEEEEEEEE \r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::O SS::::::SSSSS E:::::::::::::::E \r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::O SSS::::::::SS E:::::::::::::::E \r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::O SSSSSS::::S E::::::EEEEEEEEEE \r\n");
// PLATFORM_LOG(VERB_VERBOSE, "C:::::C L:::::L O:::::O O:::::O S:::::S E:::::E \r\n");
// PLATFORM_LOG(VERB_VERBOSE, " C:::::C CCCCCC L:::::L LLLLLLO::::::O O::::::O S:::::S E:::::E EEEEEE\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " C:::::CCCCCCCC::::CLL:::::::LLLLLLLLL:::::LO:::::::OOO:::::::OSSSSSSS S:::::SEE::::::EEEEEEEE:::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CC:::::::::::::::CL::::::::::::::::::::::L OO:::::::::::::OO S::::::SSSSSS:::::SE::::::::::::::::::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CCC::::::::::::CL::::::::::::::::::::::L OO:::::::::OO S:::::::::::::::SS E::::::::::::::::::::E\r\n");
// PLATFORM_LOG(VERB_VERBOSE, " CCCCCCCCCCCCCLLLLLLLLLLLLLLLLLLLLLLLL OOOOOOOOO SSSSSSSSSSSSSSS EEEEEEEEEEEEEEEEEEEEEE\r\n");
}
}
void UWB_HW_init( void )
{
Set_timeout_prepare_ranging( TIMEOUT_PREPARE_RANGING_DEFAULT );
Set_timeout_execute_ranging( TIMEOUT_EXECUTE_RANGING_DEFAULT );
Set_timeout_suspend_ranging( TIMEOUT_SUSPEND_RANGING_DEFAULT );
Set_timeout_resume_ranging( TIMEOUT_RESUME_RANGING_DEFAULT );
Set_timeout_door_operation( TIMEOUT_DOOR_OPERATION_DEFAULT );
responderReset();
HAL_Delay(10);
}
void UWB_HW_loop( void )
{
}

View File

@@ -0,0 +1,370 @@
/**
******************************************************************************
* @file : flash_mng.c
* @brief : Flash management functions
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "flash_mng.h"
#if defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
#include "app_ble.h"
#include "flash_manager.h"
#define FLASH_MANAGER_ENABLE 1
#endif //defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
#if FLASH_MANAGER_ENABLE
#define WRITE_BUF_SZ (1400)
/* Private variables ---------------------------------------------------------*/
static FM_CallbackNode_t Aliro_FlashCallback;
static uint8_t writeBuf[WRITE_BUF_SZ];
static uint32_t writeBufSz;
static uint32_t writeBufAddr;
/* Callback Definition ------------------------------------------------------*/
void Aliro_FlashManagerCallback(FM_FlashOp_Status_t Status)
{
FM_Cmd_Status_t fm_result;
if(Status == FM_OPERATION_AVAILABLE)
{
Aliro_FlashCallback.Callback = Aliro_FlashManagerCallback;
fm_result = FM_Write((uint32_t*)writeBuf, (uint32_t *)writeBufAddr, writeBufSz, &Aliro_FlashCallback);
if(fm_result == FM_BUSY)
{
//TODO : appropriate error handling
}
}
else
{
}
}
#endif //FLASH_MANAGER_ENABLE
/* Private function prototypes -----------------------------------------------*/
/**
* @brief Gets the page of a given address
* @param Addr: Address of the FLASH Memory
* @retval The page of a given address
*/
static uint32_t GetPage(uint32_t Addr)
{
return (Addr - FLASH_BASE) / FLASH_PAGE_SIZE;;
}
/* Public functions -----------------------------------------------*/
flashOpStatus_e EraseFlash(uint32_t nAddress, uint32_t nBytes)
{
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t FirstPage = 0, NbOfPages = 0;
uint32_t PageError = 0;
UNUSED(EraseInitStruct);
UNUSED(PageError);
/* Erase the user Flash area
(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
/* Get the 1st page to erase */
FirstPage = GetPage(nAddress);
/* Get the number of pages to erase from 1st page */
NbOfPages = GetPage(nAddress + nBytes) - FirstPage + 1;
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = FirstPage;
EraseInitStruct.NbPages = NbOfPages;
#if FLASH_MANAGER_ENABLE
FM_Cmd_Status_t fm_result;
fm_result = FM_Erase(FirstPage, NbOfPages, NULL);
if (fm_result == FM_BUSY)
{
return FLASH_OP_BUSY;
}
else if (fm_result == FM_ERROR)
{
return FLASH_OP_ERROR;
}
#else //FLASH_MANAGER_ENABLE
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK)
{
/*
Error occurred while page erase.
User can add here some code to deal with this error.
PageError will contain the faulty page and then to know the code error on this page,
user can call function 'HAL_FLASH_GetError()'
*/
/* Infinite loop */
while (1)
{
Error_Handler();
}
}
#endif //FLASH_MANAGER_ENABLE
return FLASH_OP_OK;
}
flashOpStatus_e EraseWriteToFlash(void *datapointer, uint32_t nBytes, uint32_t nAddress)
{
flashOpStatus_e result = FLASH_OP_OK;
/* Disable instruction cache prior to internal cacheable memory update */
#ifndef STM32WBAxx_LL_ICACHE_H
if (HAL_ICACHE_Disable() != HAL_OK)
{
Error_Handler();
}
#else //STM32WBAxx_LL_ICACHE_H
uint32_t tickstart;
/* Make sure BSYENDF is reset before to disable the instruction cache */
/* as it automatically starts a cache invalidation procedure */
LL_ICACHE_ClearFlag_BSYEND();
LL_ICACHE_Disable();
/* Get tick */
tickstart = HAL_GetTick();
/* Wait for instruction cache being disabled */
while (LL_ICACHE_IsEnabled())
{
if ((HAL_GetTick() - tickstart) > 1U)
{
/* New check to avoid false timeout detection in case of preemption */
if (LL_ICACHE_IsEnabled())
{
// status = HAL_TIMEOUT;
//break;
Error_Handler();
}
}
}
#endif // STM32WBAxx_LL_ICACHE_H
#if FLASH_MANAGER_ENABLE
result = EraseFlash(nAddress, nBytes);
if (result != FLASH_OP_OK)
{
return result;
}
else
{
FM_Cmd_Status_t fm_result;
int32_t int32_size = 0;
int32_size = (int32_t)(nBytes/4);
if (nBytes%4)
{
int32_size++;
}
if(nBytes > WRITE_BUF_SZ)
{
result = FLASH_OP_ERROR;
}
else
{
writeBufAddr = nAddress;
writeBufSz = int32_size;
memcpy(writeBuf, datapointer, nBytes);
result = FLASH_OP_BUSY;
}
Aliro_FlashCallback.Callback = Aliro_FlashManagerCallback;
fm_result = FM_Write((uint32_t*)writeBuf, (uint32_t *)writeBufAddr, writeBufSz, &Aliro_FlashCallback);
if(fm_result == FM_BUSY)
{
if(nBytes > WRITE_BUF_SZ)
{
result = FLASH_OP_ERROR;
}
else
{
result = FLASH_OP_BUSY;
}
}
else if (fm_result == FM_ERROR)
{
result = FLASH_OP_ERROR;
}
result = FLASH_OP_OK;
}
#else //FLASH_MANAGER_ENABLE
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Program the user Flash area word by word
(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
result = EraseFlash(nAddress, nBytes);
uint32_t AddressOffset = 0;
while (AddressOffset < nBytes)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, nAddress + AddressOffset, ((uint32_t)datapointer + AddressOffset)) == HAL_OK)
{
AddressOffset = AddressOffset + 16; /* increment to next quad word*/
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
Error_Handler();
}
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) *********/
HAL_FLASH_Lock();
#endif //FLASH_MANAGER_ENABLE
/* Re-enable instruction cache */
#ifndef STM32WBAxx_LL_ICACHE_H
if (HAL_ICACHE_Enable() != HAL_OK)
{
Error_Handler();
}
#else //STM32WBAxx_LL_ICACHE_H
LL_ICACHE_Enable();
#endif // STM32WBAxx_LL_ICACHE_H
return result;
}
flashOpStatus_e WriteToFlash(void *datapointer, uint32_t nBytes, uint32_t nAddress)
{
flashOpStatus_e result = FLASH_OP_OK;
/* Disable instruction cache prior to internal cacheable memory update */
#ifndef STM32WBAxx_LL_ICACHE_H
if (HAL_ICACHE_Disable() != HAL_OK)
{
Error_Handler();
}
#else //STM32WBAxx_LL_ICACHE_H
uint32_t tickstart;
/* Make sure BSYENDF is reset before to disable the instruction cache */
/* as it automatically starts a cache invalidation procedure */
LL_ICACHE_ClearFlag_BSYEND();
LL_ICACHE_Disable();
/* Get tick */
tickstart = HAL_GetTick();
/* Wait for instruction cache being disabled */
while (LL_ICACHE_IsEnabled())
{
if ((HAL_GetTick() - tickstart) > 1U)
{
/* New check to avoid false timeout detection in case of preemption */
if (LL_ICACHE_IsEnabled())
{
// status = HAL_TIMEOUT;
//break;
Error_Handler();
}
}
}
#endif // STM32WBAxx_LL_ICACHE_H
#if FLASH_MANAGER_ENABLE
FM_Cmd_Status_t fm_result;
int32_t int32_size = 0;
int32_size = (int32_t)(nBytes/4);
if (nBytes%4)
{
int32_size++;
}
fm_result = FM_Write((uint32_t*)datapointer, (uint32_t *)nAddress, int32_size, NULL);
if(fm_result == FM_BUSY)
{
result = FLASH_OP_BUSY;
}
else if (fm_result == FM_ERROR)
{
result = FLASH_OP_ERROR;
}
result = FLASH_OP_OK;
#else //FLASH_MANAGER_ENABLE
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Program the user Flash area word by word
(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
uint32_t AddressOffset = 0;
while (AddressOffset < nBytes)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, nAddress + AddressOffset, ((uint32_t)datapointer + AddressOffset)) == HAL_OK)
{
AddressOffset = AddressOffset + 16; /* increment to next quad word*/
}
else
{
/* Error occurred while writing data in Flash memory.
User can add here some code to deal with this error */
while (1)
{
Error_Handler();
}
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) *********/
HAL_FLASH_Lock();
#endif //FLASH_MANAGER_ENABLE
/* Re-enable instruction cache */
#ifndef STM32WBAxx_LL_ICACHE_H
if (HAL_ICACHE_Enable() != HAL_OK)
{
Error_Handler();
}
#else //STM32WBAxx_LL_ICACHE_H
LL_ICACHE_Enable();
#endif // STM32WBAxx_LL_ICACHE_H
return result;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,938 @@
/**
******************************************************************************
* @file : sm_crypto_mcu.c
* @brief : MCU cryptographic functions using hardware accelerators
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ----------------------------------------------------------*/
#include "sm_crypto_mcu.h"
#include <string.h>
#include <stdlib.h>
#ifdef STM32WBA65xx
#include "hw.h"
#endif //STM32WBA65xx
#define USE_MCU_HW_RNG
#define USE_MCU_HW_ASYM
#define HASH_TIMEOUT ((uint32_t)5)
#define KDH_INFO_MAX_LEN_BYTES ((uint32_t)32)
#define SHA256_BYTE_SIZE ((uint32_t)32)
static HASH_HandleTypeDef *HHash = NULL;
static CRYP_HandleTypeDef *HCryp = NULL;
#ifdef USE_MCU_HW_RNG
static RNG_HandleTypeDef *HRng = NULL;
#endif // USE_MCU_HW_RNG
#if defined(STM32U545xx) || defined(STM32U585xx)
#include "stm32u5xx_hal.h"
#define HHASH_INIT_DATATYPE HASH_DATATYPE_8B
#define SM_HASH_SHA256_START HAL_HASHEx_SHA256_Start
#define SM_HASH_SHA256_ACCUMULATE(H, B, S, T) HAL_HASHEx_SHA256_Accmlt(H, B, S)
#define SM_HASH_SHA256_ACCUMULATE_LAST HAL_HASHEx_SHA256_Accmlt_End
#define SM_HASH_SHA1_START HAL_HASH_SHA1_Start
#define HASH_SET_ALGORITHM(I, A)
#define SM_HMAC_SHA256_START HAL_HMACEx_SHA256_Start
#elif defined(STM32U385xx)
#include "stm32u3xx_hal.h"
#define HHASH_INIT_DATATYPE HASH_DATATYPE_8B
#define SM_HASH_SHA256_START HAL_HASHEx_SHA256_Start
#define SM_HASH_SHA256_ACCUMULATE(H, B, S, T) HAL_HASHEx_SHA256_Accmlt(H, B, S)
#define SM_HASH_SHA256_ACCUMULATE_LAST HAL_HASHEx_SHA256_Accmlt_End
#define SM_HASH_SHA1_START HAL_HASH_SHA1_Start
#define HASH_SET_ALGORITHM(I, A)
#define SM_HMAC_SHA256_START HAL_HMACEx_SHA256_Start
#elif defined(STM32WBA52xx) || defined(STM32WBA55xx) || defined(STM32WBA65xx)
#include "stm32wbaxx_hal.h"
#define HHASH_INIT_DATATYPE HASH_CR_DATATYPE_1
#define SM_HASH_SHA1_START(hhash, pInBuffer, Size, pOutBuffer, Timeout) HAL_HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout)
#define SM_HASH_SHA256_START(hhash, pInBuffer, Size, pOutBuffer, Timeout) HAL_HASH_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout)
#define SM_HMAC_SHA256_START(hhash, pInBuffer, Size, pOutBuffer, Timeout) HAL_HASH_HMAC_Start(hhash, pInBuffer, Size, pOutBuffer, Timeout)
#define SM_HASH_SHA256_ACCUMULATE(H, B, S, T) HAL_HASH_Accumulate(H, B, S, T)
#define SM_HASH_SHA256_ACCUMULATE_LAST HAL_HASH_AccumulateLast
#define HASH_SET_ALGORITHM(I, A) I.Algorithm = A
#else
#error "product not supported"
#endif
#ifdef USE_MCU_HW_ASYM
static PKA_HandleTypeDef *HPka = NULL;
#define PKA_TIMEOUT ((uint32_t)3000)
#define PRIVATE_KEY_SIZE_BYTES ((uint32_t)32)
#define MODULUS_SIZE_BYTES PRIVATE_KEY_SIZE_BYTES
#define MODULUS_SIZE_WORDS ((MODULUS_SIZE_BYTES + 3)/4)
#define SECP256R1_ORDER_LEN_BITS ((uint32_t)256)
#define SECP256R1_A_SIGN ((uint32_t)1)
static const uint8_t SECP256R1_Prime[] =
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static const uint8_t SECP256R1_AbsA[] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03 };
static const uint8_t SECP256R1_B[] =
{ 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76,
0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b,
0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b };
static const uint8_t SECP256R1_Gx[] =
{ 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63,
0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4,
0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96 };
static const uint8_t SECP256R1_Gy[] =
{ 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c,
0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb,
0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 };
static const uint8_t SECP256R1_Order[] =
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3,
0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51 };
static const uint8_t SECP256R1_OrderMinus1[] =
{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3,
0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x50 };
#ifdef ALIRO_TEST
// This is the static private key from the static test vectors
const uint8_t staticPrivateKey[] = {0x7a, 0x9e, 0x50, 0xa1, 0x9a, 0xe3, 0x85, 0xe3, 0x9b, 0x3b, 0xf0, 0xc7, 0x5e, 0xb5, 0xf9, 0xc9, 0xa5, 0xeb, 0x4d, 0x51, 0xf8, 0x8, 0x23, 0x18, 0x35, 0x39, 0x5f, 0xd2, 0xc1, 0x7, 0x83, 0x67};
#define STATIC_PRIVATE_KEY staticPrivateKey
#else // ALIRO_TEST
// This is the static private key for the mobile phone app.
//ST OFFICE
//const uint8_t staticPrivateKey[] = {0xCB, 0x64, 0xA5, 0x8A, 0x5F, 0xAE, 0x05, 0x2D, 0x45, 0x8B, 0x3B, 0xCE, 0x25, 0x99, 0xA2, 0x0A,
// 0x66, 0x59, 0x87, 0xB5, 0x37, 0xB1, 0x57, 0xCC, 0x3C, 0xC4, 0x2E, 0x1D, 0x9C, 0x65, 0x24, 0x09};
//HOME
//const uint8_t staticPrivateKey[] = {0xBE, 0x08, 0x3F, 0xCD, 0xA3, 0x7B, 0xB2, 0xDA, 0x82, 0x66, 0xDC, 0x64, 0x61, 0x66, 0x35, 0x24,
// 0xE5, 0x9A, 0xD4, 0xA0, 0xBB, 0x6B, 0x4D, 0xD3, 0x1C, 0x88, 0x53, 0xC2, 0x0F, 0xFB, 0xB4, 0x0D};
#include "provisioning.h"
#define STATIC_PRIVATE_KEY (getProvisioningFromFlash()->staticPrivateKey)
#endif // ALIRO_TEST
uint8_t ephemeralPrivateKey[] = {0x3c, 0xf, 0x74, 0x11, 0x4c, 0xd2, 0xa0, 0x21, 0xe8, 0x6, 0x6e, 0xfb, 0xaa, 0x31, 0xdb, 0xb9, 0x7e, 0xf0, 0x5, 0x42, 0x72, 0x19, 0x26, 0x6, 0xfd, 0x96, 0x63, 0x3a, 0x4, 0xf6, 0x62, 0x14};
#endif // USE_MCU_HW_ASYM
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif //GET_UINT32_BE
/**
* @brief Initializes MCU cryptographic hardware modules.
* @param rng Pointer to RNG handle.
* @param pka Pointer to PKA handle.
* @param hash Pointer to HASH handle.
* @param cryp Pointer to CRYP handle.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_initCryptoMCU(RNG_HandleTypeDef *rng, PKA_HandleTypeDef *pka, HASH_HandleTypeDef *hash, CRYP_HandleTypeDef *cryp)
{
#ifdef USE_MCU_HW_RNG
HRng = rng;
#endif // USE_MCU_HW_RNG
#ifdef USE_MCU_HW_ASYM
HPka = pka;
#endif // USE_MCU_HW_ASYM
HHash = hash;
HCryp = cryp;
return SM_Crypto_OK;
}
#ifdef USE_MCU_HW_RNG
/**
* @brief Generates random bytes using MCU hardware RNG.
* @param bytes Pointer to output buffer.
* @param size Number of bytes to generate.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_genRandomBytes(uint8_t *bytes, uint32_t size)
{
uint32_t temp;
uint32_t remain = size % 4;
if (HRng == NULL)
return(SM_Crypto_HW_Error);
__HAL_RCC_RNG_CLK_ENABLE();
__HAL_RNG_ENABLE(HRng);
#ifdef STM32WBA65xx
HW_RNG_Start();
#endif //STM32WBA65xx
for (uint32_t i = 0; i < size / 4; i++)
{
#ifdef STM32WBA65xx
HW_RNG_Get(1, &temp);
#endif //STM32WBA65xx
#if defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
if (HAL_RNG_GenerateRandomNumber(HRng, &temp) != HAL_OK)
{
/* Random number generation error */
return (SM_Crypto_HW_Error);
}
#endif //defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
#if defined(STM32WBA52xx)||defined(STM32WBA55xx)
if (HAL_RNG_GenerateRandomNumber(HRng, &temp) != HAL_OK)
{
/* Random number generation error */
return (SM_Crypto_HW_Error);
}
#endif //defined(STM32WBA52xx)||defined(STM32WBA55xx)
*(uint32_t *) bytes = temp;
bytes += 4;
}
if (remain)
{
#ifdef STM32WBA65xx
HW_RNG_Get(1, &temp);
#endif //STM32WBA65xx
#if defined(STM32WBA52xx)||defined(STM32WBA55xx)
if (HAL_RNG_GenerateRandomNumber(HRng, &temp) != HAL_OK)
{
/* Random number generation error */
return (SM_Crypto_HW_Error);
}
#endif //defined(STM32WBA52xx)||defined(STM32WBA55xx)
#if defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
if (HAL_RNG_GenerateRandomNumber(HRng, &temp) != HAL_OK)
{
/* Random number generation error */
return (SM_Crypto_HW_Error);
}
#endif //defined(STM32U545xx) || defined(STM32U585xx) || defined(STM32U385xx)
for (uint32_t i = 0; i < remain; i++)
{
*bytes = (temp >> i) & 0xFF;
bytes++;
}
}
return SM_Crypto_OK;
}
#else //USE_MCU_HW_RNG
#if 0
SM_Crypto_Error_t SM_genRandomBytes(uint8_t *bytes, uint32_t size)
{
for(uint32_t i = 0; i< size;i++)
{
*bytes = i;
}
return SM_Crypto_OK;
}
#endif
#endif // USE_MCU_HW_RNG
#ifdef USE_MCU_HW_ASYM
static uint32_t NumberOfWords(uint32_t NumberOfBytes)
{
return ((NumberOfBytes + 3) / 4);
}
static SM_Crypto_Error_t GeneratePrivateKey(uint8_t *pPrivateKey)
{
/* for NIST compliance (to decrease bias below 2^-64)
* generate random with 64 extra bits (2 words)
* perform modular reduction by n-1
* and add 1 */
uint8_t temp[MODULUS_SIZE_BYTES + 8] = { 0 };
uint8_t temp2[MODULUS_SIZE_BYTES + 8] = { 0 };
uint32_t random_bitstring_len_in_bits = 0;
PKA_ModRedInTypeDef in_modred = { 0 };
random_bitstring_len_in_bits = SECP256R1_ORDER_LEN_BITS + 64;
if (SM_genRandomBytes(temp, (random_bitstring_len_in_bits + 7) / 8) != SM_Crypto_OK)
{
return (SM_Crypto_HW_Error);
}
/* Perform modular reduction by n-1 */
in_modred.pMod = SECP256R1_OrderMinus1;
in_modred.modSize = sizeof(SECP256R1_Order);
in_modred.pOp1 = (uint32_t*)temp;
in_modred.OpSize = (random_bitstring_len_in_bits + 31) / 32;
if (HAL_PKA_ModRed(HPka, &in_modred, PKA_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
HAL_PKA_Arithmetic_GetResult(HPka, (uint32_t*)temp2);
/* compute reduced_random + 1 */
memset(temp, 0, sizeof(temp));
temp[0] = 1;
{
PKA_AddInTypeDef in_add;
in_add.pOp1 = (uint32_t*)temp2;
in_add.pOp2 = (uint32_t*)temp;
in_add.size = NumberOfWords(sizeof(SECP256R1_Order));
if (HAL_PKA_Add(HPka, &in_add, PKA_TIMEOUT) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
HAL_PKA_Arithmetic_GetResult(HPka, (uint32_t*)temp2);
}
memcpy(pPrivateKey, temp2, sizeof(SECP256R1_Order));
return SM_Crypto_OK;
}
static SM_Crypto_Error_t GeneratePublicKey(const uint8_t *pPrivateKey, uint8_t *pPublicKey)
{
PKA_ECCMulInTypeDef in_mult =
{ 0 };
/* Compute public key */
in_mult.modulusSize = sizeof(SECP256R1_Prime);
in_mult.coefSign = SECP256R1_A_SIGN;
in_mult.coefA = SECP256R1_AbsA;
in_mult.coefB = SECP256R1_B;
in_mult.modulus = SECP256R1_Prime;
in_mult.pointX = SECP256R1_Gx;
in_mult.pointY = SECP256R1_Gy;
in_mult.primeOrder = SECP256R1_Order;
in_mult.scalarMulSize = sizeof(SECP256R1_Order); // WRONG NAMING IN HAL STRUCT: this must be the length of the ORDER
in_mult.scalarMul = (uint8_t *)pPrivateKey;
{
PKA_ECCMulOutTypeDef mulRes;
mulRes.ptX = &pPublicKey[0];
mulRes.ptY = &pPublicKey[sizeof(SECP256R1_Order)];
if (HAL_PKA_ECCMul(HPka, &in_mult, PKA_TIMEOUT) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
HAL_PKA_ECCMul_GetResult(HPka, &mulRes);
}
return SM_Crypto_OK;
}
/**
* @brief Performs ECDH key agreement using MCU hardware.
* @param pPublicKey Pointer to public key.
* @param pSharedSecret Pointer to output shared secret.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_Ecdh(const uint8_t *pPublicKey, uint8_t *pSharedSecret)
{
PKA_ECCMulInTypeDef in_mult = { 0 };
/* Compute ECDH */
in_mult.modulusSize = sizeof(SECP256R1_Prime);
in_mult.coefSign = SECP256R1_A_SIGN;
in_mult.coefA = SECP256R1_AbsA;
in_mult.coefB = SECP256R1_B;
in_mult.modulus = SECP256R1_Prime;
in_mult.pointX = (uint8_t*)&pPublicKey[0];
in_mult.pointY = (uint8_t*)&pPublicKey[sizeof(SECP256R1_Order)];
in_mult.primeOrder = SECP256R1_Order;
in_mult.scalarMulSize = sizeof(SECP256R1_Order); // WRONG NAMING IN HAL STRUCT: this must be the length of the ORDER
in_mult.scalarMul = ephemeralPrivateKey;
if (HAL_PKA_ECCMul(HPka, &in_mult, PKA_TIMEOUT) != HAL_OK)
{
memset(ephemeralPrivateKey, 0, sizeof(ephemeralPrivateKey));
return SM_Crypto_Error;
}
memset(ephemeralPrivateKey, 0, sizeof(ephemeralPrivateKey));
{
PKA_ECCMulOutTypeDef pub;
uint8_t tmp[sizeof(SECP256R1_Order)];
pub.ptX = pSharedSecret;
pub.ptY = tmp;
HAL_PKA_ECCMul_GetResult(HPka, &pub);
}
return SM_Crypto_OK;
}
/**
* @brief Signs a digest using MCU hardware.
* @param digest Pointer to digest to sign.
* @param digestSize Size of digest.
* @param signature Pointer to output signature.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sign(const uint8_t *digest, uint32_t digestSize, uint8_t *signature)
{
uint8_t a_k[MODULUS_SIZE_WORDS*sizeof(uint32_t)] =
{ 0 };
PKA_ECDSASignInTypeDef in =
{ 0 };
if (digestSize != SHA256_BYTE_SIZE)
return SM_Crypto_Error;
/* generate random k parameter in NIST compliant way */
if (GeneratePrivateKey(a_k) != SM_Crypto_OK)
{
return (SM_Crypto_HW_Error);
}
/* Set input parameters */
in.primeOrderSize = sizeof(SECP256R1_Order);
in.modulusSize = sizeof(SECP256R1_Prime);
in.coefSign = SECP256R1_A_SIGN;
in.coef = SECP256R1_AbsA;
in.coefB = SECP256R1_B;
in.modulus = SECP256R1_Prime;
in.basePointX = SECP256R1_Gx;
in.basePointY = SECP256R1_Gy;
in.primeOrder = SECP256R1_Order;
in.integer = a_k;
in.hash = digest;
in.privateKey = STATIC_PRIVATE_KEY;
if (HAL_PKA_ECDSASign(HPka, &in, PKA_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
{
PKA_ECDSASignOutTypeDef out;
out.RSign = &signature[0];
out.SSign = &signature[sizeof(SECP256R1_Order)];
HAL_PKA_ECDSASign_GetResult(HPka, &out, NULL);
}
return SM_Crypto_OK;
}
/**
* @brief Generates a keypair using MCU hardware.
* @param pub Pointer to output public key.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_genKeypair(uint8_t *pub)
{
if (GeneratePrivateKey(ephemeralPrivateKey) != SM_Crypto_OK)
return SM_Crypto_Error;
if (GeneratePublicKey(ephemeralPrivateKey, pub) != SM_Crypto_OK)
{
memset(ephemeralPrivateKey, 0, sizeof(ephemeralPrivateKey));
return SM_Crypto_Error;
}
return SM_Crypto_OK;
}
/**
* @brief Verifies a signature using MCU hardware.
* @param pPublicKey Pointer to public key.
* @param digest Pointer to digest.
* @param digestSize Size of digest.
* @param signature Pointer to signature.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_verify(const uint8_t *pPublicKey, const uint8_t *digest, const uint32_t digestSize, const uint8_t *signature)
{
PKA_ECDSAVerifInTypeDef in =
{ 0 };
if (digestSize != SHA256_BYTE_SIZE)
return (SM_Crypto_Error);
/* Set input parameters */
in.primeOrderSize = sizeof(SECP256R1_Order);
in.modulusSize = sizeof(SECP256R1_Prime);
in.coefSign = SECP256R1_A_SIGN;
in.coef = SECP256R1_AbsA;
in.modulus = SECP256R1_Prime;
in.basePointX = SECP256R1_Gx;
in.basePointY = SECP256R1_Gy;
in.primeOrder = SECP256R1_Order;
in.RSign = &signature[0];
in.SSign = &signature[PRIVATE_KEY_SIZE_BYTES];
in.hash = digest;
in.pPubKeyCurvePtX = &pPublicKey[0];
in.pPubKeyCurvePtY = &pPublicKey[MODULUS_SIZE_BYTES];
if (HAL_PKA_ECDSAVerif(HPka, &in, PKA_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
if (!HAL_PKA_ECDSAVerif_IsValidSignature(HPka))
return (SM_Crypto_Error);
return SM_Crypto_OK;
}
/**
* @brief Gets the certificate from MCU hardware.
* @param certificate Pointer to output certificate buffer.
* @param certificateSize Pointer to output certificate size.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_getCertificate(uint8_t *certificate, uint32_t *certificateSize)
{
return SM_Crypto_OK;
}
#endif // USE_MCU_HW_ASYM
/* Private function -----------------------------------------------*/
static SM_Crypto_Error_t KDFKeyExpansionRound(const uint8_t* pKDK, const uint8_t *prev, const uint8_t* pFixedInfo, uint32_t fixedInfoSize, uint8_t counter, uint8_t* output)
{
/* counter and L must be big-endian, update least significant byte */
uint32_t offset = 0;
uint32_t hmac_input_size = 0;
uint8_t input[SHA256_BYTE_SIZE + MAX_FIXED_INFO_SIZE + 1 ];
if (fixedInfoSize > MAX_FIXED_INFO_SIZE)
return SM_Crypto_Error;
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA256);
HHash->Init.KeySize = SHA256_BYTE_SIZE;
HHash->Init.pKey = (uint8_t *)pKDK;
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
hmac_input_size = SHA256_BYTE_SIZE + fixedInfoSize + 1 ;
if (counter != 1)
{
memcpy(input + offset, prev, SHA256_BYTE_SIZE);
offset += SHA256_BYTE_SIZE;
} else {
/* No need to copy, but will hmac 32 bytes less */
hmac_input_size -= SHA256_BYTE_SIZE;
}
/* Based on RFC 5869 */
memcpy(input + offset, pFixedInfo, fixedInfoSize);
offset += fixedInfoSize;
memcpy(input + offset, &counter, 1);
offset += 1;
if (SM_HMAC_SHA256_START(HHash, input, hmac_input_size, output, 5000) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
return SM_Crypto_OK;
}
/* Public functions -----------------------------------------------*/
/**
* @brief Computes SHA-1 hash using MCU hardware.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @param hash Pointer to output hash buffer.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sha1(uint8_t *input, uint32_t inputSize, uint8_t *hash)
{
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA1);
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
if (SM_HASH_SHA1_START(HHash, input, inputSize, &hash[0], HASH_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
return SM_Crypto_OK;
}
/**
* @brief Computes SHA-256 hash using MCU hardware.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @param hash Pointer to output hash buffer.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sha256(uint8_t *input, uint32_t inputSize, uint8_t *hash)
{
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA256);
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
if (SM_HASH_SHA256_START(HHash, input, inputSize, &hash[0], HASH_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
return SM_Crypto_OK;
}
/**
* @brief Starts SHA-256 computation using MCU hardware.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sha256_start(void)
{
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA256);
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
return SM_Crypto_OK;
}
/**
* @brief Updates SHA-256 computation with new data using MCU hardware.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sha256_update(const uint8_t *input, uint32_t inputSize)
{
if (SM_HASH_SHA256_ACCUMULATE(HHash, input, inputSize, HASH_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
return SM_Crypto_OK;
}
/**
* @brief Finishes SHA-256 computation and returns the hash using MCU hardware.
* @param hash Pointer to output hash buffer.
* @param input Pointer to input data.
* @param inputSize Size of input data.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_sha256_finish(uint8_t *hash, const uint8_t *input, uint32_t inputSize)
{
if (SM_HASH_SHA256_ACCUMULATE_LAST(HHash, input, inputSize, &hash[0], HASH_TIMEOUT) != HAL_OK)
{
return (SM_Crypto_HW_Error);
}
return SM_Crypto_OK;
}
/**
* @brief Performs randomness extraction for KDF.
* @param Z Pointer to input keying material.
* @param ZSize Size of input keying material.
* @param salt Pointer to salt.
* @param saltSize Size of salt.
* @param output Pointer to output buffer.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t KDFRandomnessExtraction(const uint8_t* Z, uint32_t ZSize,
const uint8_t* salt, uint32_t saltSize,
uint8_t* output)
{
uint8_t null_salt[SHA256_BYTE_SIZE] = {0};
if ((saltSize == 0) && (salt == NULL)) // no salt (optionnal), need to use string of zeros, the size is the size of the HASH
{
HHash->Init.KeySize = SHA256_BYTE_SIZE;
HHash->Init.pKey = null_salt;
} else if (salt == NULL) // saltsize is non-zero but pointer is null -> error
{
return SM_Crypto_Error;
}
else
{
HHash->Init.KeySize = saltSize;
HHash->Init.pKey = (uint8_t *)salt;
}
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA256);
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
if (SM_HMAC_SHA256_START(HHash, (uint8_t *)Z, ZSize, output, 5000) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
return SM_Crypto_OK;
}
/**
* @brief Key Derivation Function RFC5869 using MCU hardware.
* @param pZ Pointer to input keying material.
* @param ZSize Size of input keying material.
* @param pSalt Pointer to salt.
* @param saltSize Size of salt.
* @param pFixedInfo Pointer to fixed info.
* @param fixedInfoSize Size of fixed info.
* @param L Length of output keying material.
* @param pOutput Pointer to output buffer.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_KDFRFC5869(const uint8_t* pZ, uint32_t ZSize,
const uint8_t* pSalt, uint32_t saltSize,
const uint8_t* pFixedInfo, uint32_t fixedInfoSize,
uint32_t L, uint8_t* pOutput)
{
uint8_t counter = 0;
uint8_t KDK[SHA256_BYTE_SIZE] = {0};
uint8_t *prev = NULL;
if(L >= 255*SHA256_BYTE_SIZE)
{
return SM_Crypto_HW_Error;
}
if (KDFRandomnessExtraction(pZ, ZSize, pSalt, saltSize, KDK) != SM_Crypto_OK)
{
return SM_Crypto_HW_Error;
}
for(counter=1; counter<=L/SHA256_BYTE_SIZE; counter++)
{
/* compute full rounds */
if(KDFKeyExpansionRound(KDK, prev, pFixedInfo, fixedInfoSize, counter, pOutput) != SM_Crypto_OK)
{
return SM_Crypto_HW_Error;
}
prev = pOutput;
pOutput += SHA256_BYTE_SIZE;
}
if(L % SHA256_BYTE_SIZE)
{
/* compute non full round */
uint8_t buffer[SHA256_BYTE_SIZE];
if(KDFKeyExpansionRound(KDK, prev, pFixedInfo, fixedInfoSize, counter, buffer) != SM_Crypto_OK)
{
return SM_Crypto_HW_Error;
}
memcpy(pOutput, buffer, L % SHA256_BYTE_SIZE);
}
return SM_Crypto_OK;
}
/**
* @brief Derives KDH key using MCU hardware.
* @param pZ Pointer to input keying material.
* @param info Pointer to info data.
* @param infoSize Size of info data.
* @param pKdh Pointer to output KDH key.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_deriveKdh(const uint8_t *pZ, const uint8_t * info, uint32_t infoSize, uint8_t *pKdh)
{
uint8_t counter_be[4] = {0,0,0,1};
uint32_t offset = 0;
uint8_t buf[KDH_INFO_MAX_LEN_BYTES + 32 + 4];
memcpy(&buf[offset], pZ, 32);
offset += 32;
memcpy(&buf[offset], counter_be, 4);
offset += 4;
memcpy(&buf[offset], info, infoSize);
HHash->Init.DataType = HHASH_INIT_DATATYPE;
HASH_SET_ALGORITHM(HHash->Init, HASH_ALGOSELECTION_SHA256);
if (HAL_HASH_Init(HHash) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
if (SM_HASH_SHA256_START(HHash, buf, 32 + 4 + infoSize, pKdh, 5000) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
return SM_Crypto_OK;
}
/**
* @brief Decrypts data using AES-256 GCM with MCU hardware.
* @param pKey Pointer to key.
* @param pNonce Pointer to nonce.
* @param pAad Pointer to additional authenticated data.
* @param aadSize Size of AAD.
* @param pPayload Pointer to encrypted payload.
* @param payloadSize Size of payload.
* @param pPlaintext Pointer to output plaintext buffer.
* @param pTag Pointer to authentication tag.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_aes256GcmDecrypt(const uint8_t* pKey, const uint8_t* pNonce, const uint8_t* pAad, const uint32_t aadSize,
const uint8_t* pPayload, const uint32_t payloadSize, uint8_t* pPlaintext,
const uint8_t* pTag)
{
uint32_t i = 0;
uint32_t key[8] = {0};
uint32_t iv[4] = {0};
uint32_t tag[4] = {0};
uint8_t tmp = 0;
/* !!! Beware: the last word must be padded with 0s by the caller, otherwise tag will be wrong !!! */
if (payloadSize % 4)
{
/* Must check that the padding has been properly done by caller */
if (memcmp(&pPayload[payloadSize], &i, 4 - (payloadSize % 4)))
return SM_Crypto_Error;
}
/* Format and fill AES key */
for( i=0; i < 8; i++ )
GET_UINT32_BE( key[i], pKey, 4*i );
/* Set IV with invert endianness */
for( i=0; i < 3; i++ )
GET_UINT32_BE( iv[i], pNonce, 4*i );
/* counter value must be set to 2 when processing the first block of payload */
iv[3] = 0x00000002;
HCryp->Instance = AES;
HCryp->Init.DataType = CRYP_DATATYPE_8B;
HCryp->Init.KeySize = CRYP_KEYSIZE_256B;
HCryp->Init.pKey = key;
HCryp->Init.pInitVect = iv;
HCryp->Init.Algorithm = CRYP_AES_GCM_GMAC;
HCryp->Init.Header = (uint32_t *)pAad;
HCryp->Init.HeaderSize = aadSize;
HCryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
HCryp->Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
HCryp->Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
HCryp->Init.KeyMode = CRYP_KEYMODE_NORMAL;
if (HAL_CRYP_Init(HCryp) != HAL_OK)
{
return(SM_Crypto_HW_Error);
}
if (HAL_CRYP_Decrypt(HCryp, (uint32_t *)pPayload, (uint16_t) payloadSize, (uint32_t *)pPlaintext, 5000) != HAL_OK)
return(SM_Crypto_HW_Error);
/* Last 16 bytes of plaintext is the GCM tag */
if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(HCryp, (const uint32_t *)tag, 5000) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
// constant time compare
for (i = 0; i < 4; i++)
{
tmp |= pTag[i*4] ^ (uint8_t)(tag[i] & 0xFF);
tmp |= pTag[i*4 + 1] ^ (uint8_t)((tag[i] >> 8) & 0xFF);
tmp |= pTag[i*4 + 2] ^ (uint8_t)((tag[i] >> 16) & 0xFF);
tmp |= pTag[i*4 + 3] ^ (uint8_t)((tag[i] >> 24) & 0xFF);
}
if (tmp)
{
memset(pPlaintext, 0, payloadSize);
return SM_Crypto_Error;
}
return SM_Crypto_OK;
}
/**
* @brief Encrypts data using AES-256 GCM with MCU hardware.
* @param pKey Pointer to key.
* @param pNonce Pointer to nonce.
* @param pAad Pointer to additional authenticated data.
* @param aadSize Size of AAD.
* @param pInput Pointer to input data.
* @param inputSize Size of input data.
* @param pOutput Pointer to output buffer.
* @param pOutputSize Pointer to output size.
* @return SM_Crypto_Error_t error code.
*/
SM_Crypto_Error_t SM_aes256GcmEncrypt(const uint8_t* pKey, const uint8_t* pNonce, const uint8_t* pAad, const uint32_t aadSize,
const uint8_t* pInput, const uint32_t inputSize, uint8_t* pOutput, uint32_t* pOutputSize)
{
uint32_t i = 0;
uint32_t key[8] = {0};
uint32_t iv[4] = {0};
uint32_t tag[4] = {0};
/* Workaround HAL: need to pad with 0s the last word of payload. Here we first copy the input into the output
buffer (that is at least 16 bytes longer (for the tag), and then we encrypt in place */
memcpy(pOutput, pInput, inputSize);
if ((inputSize) % 4)
memset(&pOutput[inputSize], 0, 4 - ((inputSize) % 4));
/* Format and fill AES key */
for( i=0; i < 8; i++ )
GET_UINT32_BE( key[i], pKey, 4*i );
/* Set IV with invert endianness */
for( i=0; i < 3; i++ )
GET_UINT32_BE( iv[i], pNonce, 4*i );
/* counter value must be set to 2 when processing the first block of payload */
iv[3] = 0x00000002;
HCryp->Instance = AES;
HCryp->Init.DataType = CRYP_DATATYPE_8B;
HCryp->Init.KeySize = CRYP_KEYSIZE_256B;
HCryp->Init.pKey = key;
HCryp->Init.pInitVect = iv;
HCryp->Init.Algorithm = CRYP_AES_GCM_GMAC;
HCryp->Init.Header = (uint32_t *)pAad;
HCryp->Init.HeaderSize = aadSize;
HCryp->Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE;
HCryp->Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE;
HCryp->Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ALWAYS;
HCryp->Init.KeyMode = CRYP_KEYMODE_NORMAL;
if (HAL_CRYP_Init(HCryp) != HAL_OK)
{
return(SM_Crypto_HW_Error);
}
if (HAL_CRYP_Encrypt(HCryp, (uint32_t *)pOutput, (uint16_t)inputSize, (uint32_t *)pOutput, 5000) != HAL_OK)
return(SM_Crypto_HW_Error);
/* Generate the GCM tag */
if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(HCryp, (const uint32_t *)tag, 5000) != HAL_OK)
{
return SM_Crypto_HW_Error;
}
for (i = 0; i < 4; i++) {
pOutput[inputSize + i*4] = (uint8_t)(tag[i] & 0xFF);
pOutput[inputSize + i*4 + 1] = (uint8_t)((tag[i] >> 8) & 0xFF);
pOutput[inputSize + i*4 + 2] = (uint8_t)((tag[i] >> 16) & 0xFF);
pOutput[inputSize + i*4 + 3] = (uint8_t)((tag[i] >> 24) & 0xFF);
}
*pOutputSize = inputSize + 16;
return SM_Crypto_OK;
}

View File

@@ -0,0 +1,203 @@
/**
******************************************************************************
* @file adv_trace_usart_if.c
* @author MCD Application Team
* @brief : Source file for interfacing the stm32_adv_trace to hardware
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "app_conf.h"
#include "stm32_adv_trace.h"
#include "adv_trace_usart_if.h"
/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* list all the driver interface used by the trace application. */
const UTIL_ADV_TRACE_Driver_s UTIL_TraceDriver =
{
UART_Init,
UART_DeInit,
UART_StartRx,
UART_TransmitDMA
};
/* Private variables ---------------------------------------------------------*/
/* Whether the UART should be in RX after a Transmit */
uint8_t receive_after_transmit = 0;
/* Buffer to receive 1 character */
static uint8_t cCharRx;
/* Exported macro ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void (*TxCpltCallback) ( void * );
static void (*RxCpltCallback) ( uint8_t * pData, uint16_t iSize, uint8_t cError );
static void UsartIf_TxCpltCallback ( UART_HandleTypeDef *huart );
static void UsartIf_RxCpltCallback ( UART_HandleTypeDef *huart );
static IRQn_Type get_IRQn_Type_from_DMA_HandleTypeDef (DMA_HandleTypeDef * hDmaHandler );
/* Private user code ---------------------------------------------------------*/
/**
*
*/
UTIL_ADV_TRACE_Status_t UART_Init( void (*pCallbackFunction)(void *))
{
TxCpltCallback = pCallbackFunction;
LOG_UART_HANDLER.TxCpltCallback = UsartIf_TxCpltCallback;
return UTIL_ADV_TRACE_OK;
}
/**
*
*/
UTIL_ADV_TRACE_Status_t UART_DeInit( void )
{
HAL_StatusTypeDef eResult;
eResult = HAL_UART_DeInit( &LOG_UART_HANDLER );
if ( eResult != HAL_OK )
{
LOG_UART_HANDLER.TxCpltCallback = NULL;
return UTIL_ADV_TRACE_UNKNOWN_ERROR;
}
return UTIL_ADV_TRACE_OK;
}
/**
*
*/
UTIL_ADV_TRACE_Status_t UART_StartRx( void (*pCallbackFunction)(uint8_t * pData, uint16_t iSize, uint8_t cError ) )
{
/* Configure UART in Receive mode */
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
LOG_UART_HANDLER.RxCpltCallback = &UsartIf_RxCpltCallback;
if ( pCallbackFunction != NULL )
{
RxCpltCallback = pCallbackFunction;
}
return UTIL_ADV_TRACE_OK;
}
/**
*
*/
UTIL_ADV_TRACE_Status_t UART_TransmitDMA ( uint8_t * pData, uint16_t iSize )
{
UTIL_ADV_TRACE_Status_t eStatus = UTIL_ADV_TRACE_OK;
HAL_StatusTypeDef eResult;
IRQn_Type eUseDmaTx;
eUseDmaTx = get_IRQn_Type_from_DMA_HandleTypeDef( LOG_UART_HANDLER.hdmatx );
if ( ( eUseDmaTx == GPDMA1_Channel0_IRQn ) || ( eUseDmaTx == GPDMA1_Channel1_IRQn ) ||
( eUseDmaTx == GPDMA1_Channel2_IRQn ) || ( eUseDmaTx == GPDMA1_Channel3_IRQn ) ||
( eUseDmaTx == GPDMA1_Channel4_IRQn ) || ( eUseDmaTx == GPDMA1_Channel5_IRQn ) ||
( eUseDmaTx == GPDMA1_Channel6_IRQn ) || ( eUseDmaTx == GPDMA1_Channel7_IRQn ) )
{
eResult = HAL_UART_Transmit_DMA( &LOG_UART_HANDLER, pData, iSize );
}
else
{
eResult = HAL_UART_Transmit_IT( &LOG_UART_HANDLER, pData, iSize );
}
if ( eResult != HAL_OK )
{
eStatus = UTIL_ADV_TRACE_HW_ERROR;
}
/* Check whether the UART should return in Receiver mode */
if ( receive_after_transmit )
{
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
}
return eStatus;
}
/**
*
*/
static void UsartIf_TxCpltCallback(UART_HandleTypeDef *huart)
{
/* ADV Trace callback */
TxCpltCallback(NULL);
}
/**
*
*/
static void UsartIf_RxCpltCallback(UART_HandleTypeDef *huart)
{
RxCpltCallback( &cCharRx, 1, 0 );
HAL_UART_Receive_IT( &LOG_UART_HANDLER, &cCharRx, 1 );
}
/**
* The purpose of this function is to match a DMA_HandleTypeDef as key with the corresponding IRQn_Type as value.
*
* TAKE CARE : in case of an invalid parameter or e.g. an usart/lpuart not initialized, this will lead to hard fault.
* it is up to the user to ensure the serial link is in a valid state.
*/
static IRQn_Type get_IRQn_Type_from_DMA_HandleTypeDef( DMA_HandleTypeDef * hDmaHandler )
{
if ( hDmaHandler->Instance == GPDMA1_Channel0 )
{ return GPDMA1_Channel0_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel1 )
{ return GPDMA1_Channel1_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel2 )
{ return GPDMA1_Channel2_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel3 )
{ return GPDMA1_Channel3_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel4 )
{ return GPDMA1_Channel4_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel5 )
{ return GPDMA1_Channel5_IRQn; }
if (hDmaHandler->Instance == GPDMA1_Channel6 )
{ return GPDMA1_Channel6_IRQn; }
if ( hDmaHandler->Instance == GPDMA1_Channel7 )
{ return GPDMA1_Channel7_IRQn; }
/* Values from (-1) to (-15) are already in used. This value isn't used so it should be safe.
So, if you see this value, it means you used an invalid DMA handler as input. */
return (IRQn_Type)(-666);
}

View File

@@ -0,0 +1,114 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart_if.h
* @author MCD Application Team
* @brief : Header file for stm32_adv_trace interface file
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef USART_IF_H
#define USART_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32_adv_trace.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Init the UART and associated DMA.
* @param cb tx function callback.
* @return @ref UTIL_ADV_TRACE_Status_t
*/
UTIL_ADV_TRACE_Status_t UART_Init(void (*cb)(void *));
/**
* @brief DeInit the UART and associated DMA.
* @return @ref UTIL_ADV_TRACE_Status_t
*/
UTIL_ADV_TRACE_Status_t UART_DeInit(void);
/**
* @brief send buffer to UART using DMA
* @param pdata data to be sent
* @param size of buffer p_data to be sent
* @return @ref UTIL_ADV_TRACE_Status_t
*/
UTIL_ADV_TRACE_Status_t UART_TransmitDMA(uint8_t *pdata, uint16_t size);
/**
* @brief start Rx process
* @param cb callback to receive the data
* @return @ref UTIL_ADV_TRACE_Status_t
*/
UTIL_ADV_TRACE_Status_t UART_StartRx(void (*cb)(uint8_t *pdata, uint16_t size, uint8_t error));
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* USART_IF_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,179 @@
/**
******************************************************************************
* @file app_bsp.h
* @author MCD Application Team
* @brief Interface to manage BSP.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef APP_BSP_H
#define APP_BSP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "app_conf.h"
#include "stm32_rtos.h"
#ifdef STM32WBA55xx
#ifdef CFG_BSP_ON_DISCOVERY
#include "stm32wba55g_discovery.h"
#if (CFG_LCD_SUPPORTED == 1)
#include "stm32wba55g_discovery_lcd.h"
#include "stm32_lcd.h"
#endif /* (CFG_LCD_SUPPORTED == 1) */
#endif /* CFG_BSP_ON_DISCOVERY */
#endif /* STM32WBA55xx */
#ifdef STM32WBA65xx
#ifdef CFG_BSP_ON_DISCOVERY
#include "stm32wba65i_discovery.h"
#if (CFG_LCD_SUPPORTED == 1)
#include "stm32wba65i_discovery_lcd.h"
#include "stm32_lcd.h"
#endif /* (CFG_LCD_SUPPORTED == 1) */
#endif /* CFG_BSP_ON_DISCOVERY */
#endif /* STM32WBA65xx */
#ifdef CFG_BSP_ON_CEB
#ifdef STM32WBA5Mxx
#include "b_wba5m_wpan.h"
#endif
#ifdef STM32WBA6Mxx
#include "b_wba6m_wpan.h"
#endif
#endif /* CFG_BSP_ON_CEB */
#ifdef CFG_BSP_ON_NUCLEO
#include "stm32wbaxx_nucleo.h"
#endif /* CFG_BSP_ON_CEB */
#ifdef CFG_COAP_MSG
#include "coap.h"
#endif
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
#if (CFG_LCD_SUPPORTED == 1)
#define LCD1 (0u)
#endif /* (CFG_LCD_SUPPORTED == 1) */
#if (defined CFG_BSP_ON_DISCOVERY) && (defined STM32WBA65xx)
/* No Led Blue on Discovery for STM32WBA65I. Replaced by Red Led */
#define LED_BLUE LED_RED
#endif /* (defined CFG_BSP_ON_DISCOVERY) && (defined STM32WBA65xx) */
#if (CFG_JOYSTICK_SUPPORTED == 1)
#define JOYSTICK_USE_AS_JOYSTICK (0u) /* When Joystick is not 'none', call according 'Joystick Action' every JOYSTICK_PRESS_SAMPLE_MS. */
#define JOYSTICK_USE_AS_BUTTON (1u) /* When Joystick is pressed, call according 'Joystick Action' one time. */
#define JOYSTICK_USE_AS_BUTTON_WITH_TIME (2u) /* When Joystick is pressed, it wait the release or the end of JOYSTICK_LONG_PRESS_THRESHOLD_MS
before call according 'Joystick Action'. */
#define JOYSTICK_USE_AS_CHANGE (3u) /* When Joystcik is pressed according 'Joystick Action' is called. When the Joystick is released, 'JoystickNoneAction' is called. */
#define JOYSTICK_USE_AS_MATTER (4u) /* When Joystick is pressed, according 'Joystick Action' is called. When the Joystick is released or the end
of JOYSTICK_LONG_PRESS_THRESHOLD_MS occurs, according 'Joystick Action' is called (same as when pressed). */
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
/* Exported variables --------------------------------------------------------*/
#ifdef CFG_COAP_MSG
extern uint32_t APP_Thread_TransmitPeriod_ms;
extern uint32_t APP_Thread_CoapPayloadLength_byte;
extern otCoapType APP_Thread_CoapType;
#endif
#if (CFG_BUTTON_SUPPORTED == 1)
#ifdef CFG_BSP_ON_THREADX
extern TX_SEMAPHORE ButtonB1Semaphore, ButtonB2Semaphore, ButtonB3Semaphore;
#endif /* CFG_BSP_ON_THREADX */
#ifdef CFG_BSP_ON_FREERTOS
extern osSemaphoreId_t ButtonB1Semaphore, ButtonB2Semaphore, ButtonB3Semaphore;
#endif /* CFG_BSP_ON_FREERTOS */
#endif /* (CFG_BUTTON_SUPPORTED == 1) */
#if (CFG_JOYSTICK_SUPPORTED == 1)
#ifdef CFG_BSP_ON_THREADX
extern TX_SEMAPHORE JoystickUpSemaphore, JoystickRightSemaphore, JoystickDownSemaphore, JoystickLeftSemaphore, JoystickSelectSemaphore, JoystickNoneSemaphore;
#endif /* CFG_BSP_ON_THREADX */
#ifdef CFG_BSP_ON_FREERTOS
extern osSemaphoreId_t JoystickUpSemaphore, JoystickRightSemaphore, JoystickDownSemaphore, JoystickLeftSemaphore, JoystickSelectSemaphore, JoystickNoneSemaphore;
#endif /* CFG_BSP_ON_FREERTOS */
#endif /* (CFG_JOYSTICK_SUPPORTED == 1) */
/* Exported macros ------------------------------------------------------------*/
#if ( CFG_LED_SUPPORTED == 1 )
#define APP_BSP_LED_On( LED ) BSP_LED_On( LED )
#define APP_BSP_LED_Off( LED ) BSP_LED_Off( LED )
#define APP_BSP_LED_Toggle( LED ) BSP_LED_Toggle( LED )
#else /* ( CFG_LED_SUPPORTED == 1 ) */
#define APP_BSP_LED_On( LED )
#define APP_BSP_LED_Off( LED )
#define APP_BSP_LED_Toggle( LED )
#endif /* ( CFG_LED_SUPPORTED == 1 ) */
/* Exported functions prototypes ---------------------------------------------*/
void APP_BSP_Init ( void );
void APP_BSP_PostIdle ( void );
void APP_BSP_StandbyExit ( void );
uint8_t APP_BSP_SerialCmdExecute ( uint8_t * pRxBuffer, uint16_t iRxBufferSize );
#if (CFG_LED_SUPPORTED == 1)
void APP_BSP_LedInit ( void );
#endif /* (CFG_LED_SUPPORTED == 1) */
#if (CFG_LCD_SUPPORTED == 1)
void APP_BSP_LcdInit ( void );
#endif /* (CFG_LCD_SUPPORTED == 1) */
#if ( CFG_BUTTON_SUPPORTED == 1 )
void APP_BSP_ButtonInit ( void );
uint8_t APP_BSP_ButtonIsLongPressed ( uint16_t btnIdx );
void APP_BSP_SetButtonIsLongPressed ( uint16_t btnIdx );
void APP_BSP_Button1Action ( void );
void APP_BSP_Button2Action ( void );
void APP_BSP_Button3Action ( void );
void BSP_PB_Callback ( Button_TypeDef button );
#endif /* ( CFG_BUTTON_SUPPORTED == 1 ) */
#if ( CFG_JOYSTICK_SUPPORTED == 1 )
void APP_BSP_JoystickInit ( void );
uint8_t APP_BSP_JoystickIsLongPressed ( void );
uint8_t APP_BSP_JoystickIsShortReleased ( void );
uint8_t APP_BSP_JoystickIsInitialPress ( void );
void APP_BSP_JoystickUpAction ( void );
void APP_BSP_JoystickRightAction ( void );
void APP_BSP_JoystickDownAction ( void );
void APP_BSP_JoystickLeftAction ( void );
void APP_BSP_JoystickSelectAction ( void );
void APP_BSP_JoystickNoneAction ( void );
void BSP_JOY_Callback ( JOY_TypeDef joyNb, JOYPin_TypeDef joyPin );
#endif /* CFG_JOYSTICK_SUPPORTED */
void APP_BSP_CliInit ( void );
void APP_BSP_CoapMsgRateAction ( void );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*APP_BSP_H */

View File

@@ -0,0 +1,562 @@
/**
******************************************************************************
* @file hw.h
* @author MCD Application Team
* @brief This file contains the interface of STM32 HW drivers.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef HW_H__
#define HW_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32wbaxx.h"
#include "app_conf.h"
/* ---------------------------------------------------------------------------
* General
* ---------------------------------------------------------------------------
*/
#ifndef CFG_HW_ERROR_OFFSET
#define CFG_HW_ERROR_OFFSET 0
#endif
/* Return values definition */
enum
{
HW_OK = 0,
HW_BUSY = 1
};
/*
* HW_Init
*
* This function must be called once after reset before calling any of the
* other HW functions.
*/
extern void HW_Init( void );
/*
* HW_Delay
*
* This function is used internally for minimum delays.
* The input is given in microseconds and must be strictly higher than 0 (> 0)
* and lower than 16000000 (= 16 s).
* Be careful that the actual delay can be higher than the one programmed
* if the function is interrupted.
* The function is declared "weak" and can be overloaded by the user.
*/
extern void HW_Delay( uint32_t delay_us );
/*
* HW_GetPackageType
*
* Returns the package type (cf Package Data Register in STM32WB UM)
*/
extern uint32_t HW_GetPackageType( void );
/*
* HW_Config_HSE
*/
void HW_Config_HSE( uint8_t hsetune );
/* ---------------------------------------------------------------------------
* AES
* ---------------------------------------------------------------------------
*/
/* Mode definitions used for HW_AES_SetKey() function */
enum
{
HW_AES_DEC = 0,
HW_AES_ENC = 1,
HW_AES_REV = 2,
HW_AES_SWAP = 4
};
extern int CRYP_MutexTake(void);
extern int CRYP_MutexRelease(void);
/*
* HW_AES_Enable
*
* Enables the AES hardware block.
* If the AES was already in use, the function does nothing and returns 0;
* otherwise it returns 1.
* Be careful: no re-entrance is ensured for the HW_AES functions
*/
extern int HW_AES_Enable( void );
/*
* HW_AES_SetKey
*
* Sets the key used for encryption/decryption.
* The "mode" parameter must be set to HW_AES_ENC for encryption and to
* HW_AES_DEC for decryption. It can be or-ed with HW_AES_REV for a reveresd
* oreder of key bytes, and with HW_AES_SWAP to use data byte swapping mode.
*/
extern void HW_AES_SetKey( uint32_t mode,
const uint8_t* key );
/*
* HW_AES_Crypt
*
* Encrypts/decrypts the 16-byte input data ("input"). Result is written in the
* 16-byte buffer ("output") allocated by the user.
*/
extern void HW_AES_Crypt( const uint32_t* input,
uint32_t* output );
/*
* HW_AES_Crypt
*
* Encrypts/decrypts the 16-byte input data ("input").
* Result is written in the 16-byte buffer ("output") allocated by the user.
*
* Note : input & output are 8 bits aligned.
*/
extern void HW_AES_Crypt8( const uint8_t* input, uint8_t* output );
/*
* HW_AES_Disable
*
* Disables the AES hardware block.
*/
extern void HW_AES_Disable( void );
/*
* HW_AES_InitCcm
*
* Initilaizes AES for CCM encryption (decrypt = 0) or decryption (decrypt = 1)
* Note: B0 and B1 4-word blocks must be provided by user.
*
*/
extern void HW_AES_InitCcm( uint8_t decrypt,
const uint8_t* key,
const uint32_t* b0,
const uint32_t* b1 );
/*
* HW_AES_EndCcm
*
* Completes CCM processing by computing the authentication tag
*
*/
extern void HW_AES_EndCcm( uint8_t tag_length,
uint8_t* tag );
/*
* HW_AES_SetLast
*
* Function used in CCM processing to indicate the last block of data in
* case of decryption
*
*/
extern void HW_AES_SetLast( uint8_t left_length );
/* ---------------------------------------------------------------------------
* PKA
* ---------------------------------------------------------------------------
*/
extern int PKA_MutexTake(void);
extern int PKA_MutexRelease(void);
/*
* HW_PKA_Enable
*
* Enables the PKA hardware block.
* If the driver is already in used, the function returns 0 immediately.
* If the PKA semaphore is available, this function locks the PKA semaphore,
* otherwise it returns 0.
* Then, when PKA semaphore is locked, the function enables PKA security,
* PKA clock and the block itself.
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
* Be careful: no re-entrance is ensured for the HW_PKA functions
*/
extern int HW_PKA_Enable( void );
/*
* HW_PKA_WriteSingleInput
*
* Writes one single word into the PKA memory.
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
*/
extern void HW_PKA_WriteSingleInput( uint32_t index,
uint32_t word );
/*
* HW_PKA_WriteOperand
*
* Writes one operand of size 'n' 32-bit words into the PKA memory.
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
*/
extern void HW_PKA_WriteOperand( uint32_t index,
int size,
const uint32_t* in );
/*
* HW_PKA_Start
*
* Starts the PKA operation with mode defined by the parameter "mode".
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
*
* "mode" can be one of the LL_PKA_MODE... definitions that can be found
* in "stm32wbxx_ll_pka.h" file.
*/
extern void HW_PKA_Start( uint32_t mode );
/*
* HW_PKA_EndOfOperation
*
* Returns 0 if the PKA processing is still active.
* Returns a value different from 0 when the PKA processing is complete.
*/
extern int HW_PKA_EndOfOperation( void );
/*
* HW_PKA_ReadSingleOutput
*
* Reads one 32-bit word result from the PKA memory.
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
*/
extern uint32_t HW_PKA_ReadSingleOutput( uint32_t index );
/*
* HW_PKA_ReadResult
*
* Reads one multi-word result ("size" x 32-bit words) from the PKA memory.
* This function must not be directly called when using P-256 elliptic curve
* dedicated functions.
*/
extern void HW_PKA_ReadResult( uint32_t index,
int size,
uint32_t* out );
/*
* HW_PKA_Disable
*
* Disables the PKA hardware block.
* This function disables also the PKA clock and the PKA security.
* It then releases the PKA semaphore.
*/
extern void HW_PKA_Disable( void );
/*
* Notes:
*
* - this driver uses a semaphore to handle access to the PKA. The index of
* the semaphore must be configured with CFG_HW_PKA_SEMID.
*/
/* ---------------------------------------------------------------------------
* PKA_P256
* ---------------------------------------------------------------------------
*/
/*
* HW_PKA_P256_StartRangeCheck
*
* Starts the range check of a point coordinate for P-256 elliptic curve.
*
* This function sets the parameters in PKA memory and then starts the
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
* The user must poll on the result availability by calling the
* HW_PKA_EndOfOperation() function.
*
* The input parameter is one the point coordinate. It must be a vector of
* 8 x 32-bit words (32 bytes).
*
* The check result is retrieved by calling HW_PKA_P256_IsRangeCheckOk().
*/
extern void HW_PKA_P256_StartRangeCheck( const uint32_t* coord );
/*
* HW_PKA_P256_IsRangeCheckOk
*
* Reads the result of P-256 range check. This function must only be called
* when HW_PKA_EndOfOperation() returns a non-zero value.
*
* Returns 0 if the check fails ; 1 otherwise.
*/
extern uint32_t HW_PKA_P256_IsRangeCheckOk( void );
/*
* HW_PKA_P256_StartPointCheck
*
* Starts the check of a point for P-256 elliptic curve.
*
* This function sets the parameters in PKA memory and then starts the
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
* The user must poll on the result availability by calling the
* HW_PKA_EndOfOperation() function.
*
* The input parameters are the point coordinates. Each parameter must be a
* vector of 8 x 32-bit words (32 bytes).
*
* The check result is retrieved by calling HW_PKA_P256_IsPointCheckOk().
*/
extern void HW_PKA_P256_StartPointCheck( const uint32_t* x,
const uint32_t* y );
/*
* HW_PKA_P256_IsPointCheckOk
*
* Reads the result of P-256 point check. This function must only be called
* when HW_PKA_EndOfOperation() returns a non-zero value.
*
* Returns 0 if the check fails ; 1 otherwise.
*/
extern uint32_t HW_PKA_P256_IsPointCheckOk( void );
/*
* HW_PKA_P256_StartEccScalarMul
*
* Starts the PKA scalar multiplication using the P-256 elliptic curve.
*
* This function sets the parameters in PKA memory and then starts the
* processing. The PKA has to be enabled before with HW_PKA_Enable( ).
* The user must poll on the result availability by calling the
* HW_PKA_EndOfOperation() function.
*
* The input parameter is the starting point P defined by its 2 coordinates
* p_x and p_y, and the scalar k. Each parameter must be a vector of 8 x 32-bit
* words (32 bytes).
*/
extern void HW_PKA_P256_StartEccScalarMul( const uint32_t* k,
const uint32_t* p_x,
const uint32_t* p_y );
/*
* HW_PKA_P256_ReadEccScalarMul
*
* Reads the result of PKA scalar multiplication using the P-256 elliptic
* curve. This function must only be called when HW_PKA_EndOfOperation()
* returns a non-zero value.
*
* This function retrieves the result from PKA memory: coordinates of point P,
* p_x and p_y, 8 x 32-bit words each (2 times 32 bytes).
* Before returning, it disables the PKA block, releasing the PKA semaphore.
*/
extern void HW_PKA_P256_ReadEccScalarMul( uint32_t* p_x,
uint32_t* p_y );
/* ---------------------------------------------------------------------------
* RNG
* ---------------------------------------------------------------------------
*/
/*
* The RNG driver is made to generate the random numbers in background instead
* of generating them each time they are needed by the application.
* Thus, the function HW_RNG_Process() must be called regularly in background
* loop to generate a pool of random numbers. The function HW_RNG_Get() reads
* the random numbers from the pool.
* The size of the pool must be configured with HW_RNG_POOL_SIZE.
*/
/* Error codes definition for HW_RNG return values */
enum
{
HW_RNG_CLOCK_ERROR = CFG_HW_ERROR_OFFSET + 0x101,
HW_RNG_NOISE_ERROR = CFG_HW_ERROR_OFFSET + 0x102,
HW_RNG_UFLOW_ERROR = CFG_HW_ERROR_OFFSET + 0x103,
};
/* RNG pool size */
#define HW_RNG_POOL_SIZE (CFG_HW_RNG_POOL_SIZE)
/* Default threshold to refill RNG pool */
#define HW_RNG_POOL_DEFAULT_THRESHOLD (12)
extern int RNG_MutexTake(void);
extern int RNG_MutexRelease(void);
/* RNG_KERNEL_CLK_ON
*
* Enable RNG kernel clock.
*/
void RNG_KERNEL_CLK_ON(void);
/* RNG_KERNEL_CLK_OFF
*
* Called when RNG kernel clock may be disabled.
* Weak function to be implemented by user.
*/
void RNG_KERNEL_CLK_OFF(void);
/* HW_RNG_Disable
*
* Disables the RNG peripheral and switch off its clock in RCC.
*/
extern void HW_RNG_Disable( void );
/* HW_RNG_Start
*
* Starts the generation of random numbers using the RNG IP. This function has
* to be called only once at reset before calling HW_RNG_Get() to retrieve
* the generated random values.
*/
extern void HW_RNG_Start( void );
/*
* HW_RNG_Get
*
* Retrieves "n" random 32-bit words.
* "n" must be in the range [1, CFG_HW_RNG_POOL_SIZE].
* The random numbers are written in memory from "val" pointer.
* "val" must point to a sufficient memory buffer allocated by the caller.
*/
extern void HW_RNG_Get( uint8_t n,
uint32_t* val );
/*
* HW_RNG_Process
*
* This function must be called in a separate task or in "background" loop.
* It implements a simple state machine that enables the RNG block,
* generates random numbers and then disables the RNG.
* It returns 0 (HW_OK) if the low power mode can be entered.
* It returns HW_BUSY as long as this function must be called.
* In error conditions, it returns one of the following error codes:
* - HW_RNG_CLOCK_ERROR for clock error,
* - HW_RNG_NOISE_ERROR for noise source error;
* the hardware must then be reset.
* - HW_RNG_UFLOW_ERROR in case of pool underflow error.
*/
extern int HW_RNG_Process( void );
/*
* HW_RNG_EnableClock
*
* This function enables the RNG clock for "other user" than RNG driver itself
*/
extern void HW_RNG_EnableClock( uint8_t user_mask );
/*
* HW_RNG_DisableClock
*
* This function disables the RNG clock for "other user" than RNG driver itself
*/
extern void HW_RNG_DisableClock( uint8_t user_mask );
extern void HWCB_RNG_Process( void );
/*
* HW_RNG_Init
*
* This function initializes RNG (clock, configuration ...)
*/
extern void HW_RNG_Init(void);
/*
* HW_RNG_Init
*
* Sets RNG pool threshold (for refill)
*/
extern void HW_RNG_SetPoolThreshold(uint8_t threshold);
/* ---------------------------------------------------------------------------
* GPIO
* ---------------------------------------------------------------------------
*/
/* Index definitions used for all GPIO functions */
enum
{
HW_GPIO_DBG = 0,
HW_GPIO_GREEN_LED = 13,
HW_GPIO_RED_LED = 14,
HW_GPIO_BLUE_LED = 15,
};
/*
* HW_GPIO_Init
*
* This function initilaizes the GPIO pins used for debug.
*/
extern void HW_GPIO_Init( const uint32_t* dbg_pins );
/*
* HW_GPIO_Read
*
* This function reads the output pin which index is given in parameter.
* It returns 0 if the pin is low, 1 if the pin is high.
*/
extern uint8_t HW_GPIO_Read( uint8_t index );
/*
* HW_GPIO_Set
*
* This function sets to high level the output pin which index is given
* in parameter.
*/
extern void HW_GPIO_Set( uint8_t index );
/*
* HW_GPIO_Reset
*
* This function resets to low level the output pin which index is given
* in parameter.
*/
extern void HW_GPIO_Reset( uint8_t index );
extern void GPIO_SetDebug( int gpio_pin,
int pin_value );
/* ---------------------------------------------------------------------------
* OTP
* ---------------------------------------------------------------------------
*/
typedef __PACKED_STRUCT
{
uint8_t additional_data[8]; /*!< 64 bits of data to fill OTP slot */
uint8_t bd_address[6]; /*!< Bluetooth Device Address*/
uint8_t hsetune; /*!< Load capacitance to be applied on HSE pad */
uint8_t index; /*!< Structure index */
} HW_OTP_data_t;
/*
* HW_OTP_Read
*
* Read the OTP
*
*/
int HW_OTP_Read( uint8_t index,
HW_OTP_data_t** data );
/*
* HW_OTP_Write
*
* ReadWrite the OTP
*
*/
int HW_OTP_Write( uint8_t* additional_data,
uint8_t* bd_address,
uint8_t hsetune,
uint8_t index );
#ifdef __cplusplus
}
#endif
#endif /* HW_H__ */

View File

@@ -0,0 +1,332 @@
/**
******************************************************************************
* @file hw_aes.c
* @author MCD Application Team
* @brief This file contains the AES driver for STM32WBA
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "app_common.h"
#include "stm32wbaxx_ll_bus.h"
/*****************************************************************************/
extern void Error_Handler(void);
/*****************************************************************************/
#define HW_AESX AES
#define HW_AES_CLOCK_ENABLE( ) LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_AES )
#define HW_AES_CLOCK_DISABLE( ) LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_AES )
#define HW_AES_CLOCK_IS_ENABLE( ) LL_AHB2_GRP1_IsEnabledClock( LL_AHB2_GRP1_PERIPH_AES )
#define AES_BLOCK_SIZE_WORD (4U)
#define AES_BLOCK_SIZE_BYTE (16U)
/*****************************************************************************/
typedef struct
{
uint8_t run;
} HW_AES_VAR_T;
/*****************************************************************************/
static HW_AES_VAR_T HW_AES_var;
/*****************************************************************************/
__WEAK int CRYP_MutexTake(void)
{
return 0; /* This shall be implemented by user */
}
__WEAK int CRYP_MutexRelease(void)
{
return 0; /* This shall be implemented by user */
}
/*****************************************************************************/
int HW_AES_Enable( void )
{
HW_AES_VAR_T* av = &HW_AES_var;
if (0 != CRYP_MutexTake())
{
return FALSE;
}
/* Test if the driver is not already in use */
if ( HW_AES_CLOCK_IS_ENABLE() )
{
if (0 != CRYP_MutexRelease())
{
Error_Handler();
}
return FALSE;
}
av->run = TRUE;
UTILS_ENTER_CRITICAL_SECTION( );
/* Enable AES clock */
HW_AES_CLOCK_ENABLE( );
UTILS_EXIT_CRITICAL_SECTION( );
return TRUE;
}
/*****************************************************************************/
void HW_AES_SetKey( uint32_t mode,
const uint8_t* key )
{
uint32_t tmp[4];
/* Retrieve all bytes of key */
memcpy( tmp, key, 16 );
/* Initialize the AES peripheral with default values:
- Processing: disabled
- Data type: 32-bit
- Operating mode: encryption
- Chaining mode: ECB
- Key size: 128-bit
*/
HW_AESX->CR = 0;
/* Copy key bytes to the AES registers */
if ( mode & HW_AES_REV )
{
HW_AESX->KEYR0 = tmp[0];
HW_AESX->KEYR1 = tmp[1];
HW_AESX->KEYR2 = tmp[2];
HW_AESX->KEYR3 = tmp[3];
}
else
{
HW_AESX->KEYR3 = __REV( tmp[0] );
HW_AESX->KEYR2 = __REV( tmp[1] );
HW_AESX->KEYR1 = __REV( tmp[2] );
HW_AESX->KEYR0 = __REV( tmp[3] );
}
if ( !(mode & HW_AES_ENC) )
{
/* Set key preparation mode */
HW_AESX->CR = AES_CR_MODE_0;
/* Enable AES processing */
HW_AESX->CR |= AES_CR_EN;
/* Wait for CCF flag to be raised */
while ( ! (HW_AESX->ISR & AES_ISR_CCF) );
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
/* Set decryption mode */
HW_AESX->CR = AES_CR_MODE_1;
}
/* Enable byte swapping if needed */
if ( mode & HW_AES_SWAP )
HW_AESX->CR |= AES_CR_DATATYPE_1;
/* Wait until KEYVALID is set */
while ( !(HW_AESX->SR & AES_SR_KEYVALID) );
/* Enable AES processing */
HW_AESX->CR |= AES_CR_EN;
}
/*****************************************************************************/
void HW_AES_Crypt( const uint32_t* input,
uint32_t* output )
{
/* Write the input block into the input FIFO */
HW_AESX->DINR = input[0];
HW_AESX->DINR = input[1];
HW_AESX->DINR = input[2];
HW_AESX->DINR = input[3];
/* Wait for CCF flag to be raised */
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
/* Read the output block from the output FIFO */
output[0] = HW_AESX->DOUTR;
output[1] = HW_AESX->DOUTR;
output[2] = HW_AESX->DOUTR;
output[3] = HW_AESX->DOUTR;
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
}
/*****************************************************************************/
void HW_AES_Disable( void )
{
HW_AES_VAR_T* av = &HW_AES_var;
if ( av->run )
{
/* Disable AES processing */
HW_AESX->CR = 0;
UTILS_ENTER_CRITICAL_SECTION( );
/* Disable AES clock */
HW_AES_CLOCK_DISABLE( );
UTILS_EXIT_CRITICAL_SECTION( );
if (0 != CRYP_MutexRelease())
{
Error_Handler();
}
av->run = FALSE;
}
}
/*****************************************************************************/
void HW_AES_Crypt8( const uint8_t * pInput, uint8_t * pOutput )
{
uint32_t pTemp[AES_BLOCK_SIZE_WORD];
// Transfer 8 -> 32 bits */
memcpy( pTemp, pInput, AES_BLOCK_SIZE_BYTE );
/* Write the input block into the input FIFO */
HW_AESX->DINR = __REV( pTemp[0] );
HW_AESX->DINR = __REV( pTemp[1] );
HW_AESX->DINR = __REV( pTemp[2] );
HW_AESX->DINR = __REV( pTemp[3] );
// -- Wait for CCF flag to be raised /
while ( (HW_AESX->ISR & AES_ISR_CCF) == 0x00u )
{ }
/* Read the output block from the output FIFO */
pTemp[0] = __REV( HW_AESX->DOUTR );
pTemp[1] = __REV( HW_AESX->DOUTR );
pTemp[2] = __REV( HW_AESX->DOUTR );
pTemp[3] = __REV( HW_AESX->DOUTR );
/* Transfer 32 -> 8 bits */
memcpy( pOutput, pTemp, AES_BLOCK_SIZE_BYTE );
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
}
/*****************************************************************************/
void HW_AES_InitCcm( uint8_t decrypt,
const uint8_t* key,
const uint32_t* b0,
const uint32_t* b1 )
{
uint32_t tmp[4], mode = decrypt ? AES_CR_MODE_1 : 0;
/* CCM init phase */
HW_AESX->CR = AES_CR_CHMOD_2 | mode;
/* Copy key bytes to the AES registers */
memcpy( tmp, key, 16 );
HW_AESX->KEYR0 = tmp[0];
HW_AESX->KEYR1 = tmp[1];
HW_AESX->KEYR2 = tmp[2];
HW_AESX->KEYR3 = tmp[3];
/* Copy B0 bytes to the AES registers */
HW_AESX->IVR3 = __REV( b0[0] );
HW_AESX->IVR2 = __REV( b0[1] );
HW_AESX->IVR1 = __REV( b0[2] );
HW_AESX->IVR0 = __REV( b0[3] );
/* Enable AES processing */
HW_AESX->CR |= AES_CR_EN;
/* Wait for CCF flag to be raised */
while ( ! (HW_AESX->ISR & AES_ISR_CCF) );
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
/* CCM header phase */
HW_AESX->CR = AES_CR_CHMOD_2 | AES_CR_GCMPH_0 | AES_CR_DATATYPE_1;
/* Enable AES processing */
HW_AESX->CR |= AES_CR_EN;
/* Write the header block B1 into the input FIFO */
HW_AESX->DINR = b1[0];
HW_AESX->DINR = b1[1];
HW_AESX->DINR = b1[2];
HW_AESX->DINR = b1[3];
/* Wait for CCF flag to be raised */
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
/* CCM payload phase */
HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
AES_CR_GCMPH_1 | AES_CR_DATATYPE_1 | mode);
}
/*****************************************************************************/
void HW_AES_EndCcm( uint8_t tag_length,
uint8_t* tag )
{
uint32_t tmp[4];
/* CCM final phase */
HW_AESX->CR = (AES_CR_EN | AES_CR_CHMOD_2 |
AES_CR_GCMPH_0 | AES_CR_GCMPH_1 | AES_CR_DATATYPE_1);
/* Wait for CCF flag to be raised */
while ( !(HW_AESX->ISR & AES_ISR_CCF) );
/* Read the output block from the output FIFO */
tmp[0] = HW_AESX->DOUTR;
tmp[1] = HW_AESX->DOUTR;
tmp[2] = HW_AESX->DOUTR;
tmp[3] = HW_AESX->DOUTR;
memcpy( tag, tmp, tag_length );
/* Clear CCF Flag */
HW_AESX->ICR |= AES_ICR_CCF;
}
/*****************************************************************************/
void HW_AES_SetLast( uint8_t left_length )
{
HW_AESX->CR |= (16UL - left_length) << AES_CR_NPBLB_Pos;
}
/*****************************************************************************/

View File

@@ -0,0 +1,67 @@
/**
******************************************************************************
* @file hw_if.h
* @author MCD Application Team
* @brief Hardware Interface
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef HW_IF_H
#define HW_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32wbaxx.h"
#include "stm32wbaxx_hal_conf.h"
#include "stm32wbaxx_hal_def.h"
#include "stm32wbaxx_ll_exti.h"
#include "stm32wbaxx_ll_system.h"
#include "stm32wbaxx_ll_rcc.h"
#include "stm32wbaxx_ll_bus.h"
#include "stm32wbaxx_ll_pwr.h"
#include "stm32wbaxx_ll_cortex.h"
#include "stm32wbaxx_ll_utils.h"
#include "stm32wbaxx_ll_gpio.h"
#include "stm32wbaxx_ll_rtc.h"
/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif /*HW_IF_H */

View File

@@ -0,0 +1,101 @@
/**
******************************************************************************
* @file hw_otp.c
* @author MCD Application Team
* @brief This file contains the OTP driver.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "app_common.h"
#include "stm32wbaxx_hal.h"
/*****************************************************************************/
int HW_OTP_Read( uint8_t index, HW_OTP_data_t ** otp_ptr )
{
/* OTP data:
* additional_data 8 bytes LSB
* bd_address 6 bytes
* hsetune 1 byte
* index 1 byte MSB
*/
*otp_ptr = (HW_OTP_data_t*)(FLASH_OTP_BASE + FLASH_OTP_SIZE - 16);
while ( ( (*otp_ptr)->index != index ) &&
( (*otp_ptr) != (HW_OTP_data_t*) FLASH_OTP_BASE ) )
{
(*otp_ptr) -= 1;
}
if ( (*otp_ptr)->index != index )
{
return 1; /* error */
}
return HW_OK;
}
/*****************************************************************************/
int HW_OTP_Write( uint8_t* additional_data,
uint8_t* bd_address,
uint8_t hsetune,
uint8_t index )
{
int err = 1; /* error */
HW_OTP_data_t otp;
int i;
/* Fill OTP_Data_s structure */
for ( i = 0; i < sizeof(otp.additional_data); i++ )
{
otp.additional_data[i] = additional_data[i];
}
for ( i = 0; i < sizeof(otp.bd_address); i++ )
{
otp.bd_address[i] = bd_address[i];
}
otp.hsetune = hsetune;
otp.index = index;
/* Find free space */
uint32_t free_address = FLASH_OTP_BASE;
while ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
( *(uint64_t*)(free_address + 8u) != 0xFFFFFFFFFFFFFFFFUL ) &&
( (free_address + 16u) != FLASH_OTP_BASE + FLASH_OTP_SIZE ) )
{
free_address += 16;
}
if ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
( *(uint64_t*)(free_address + 8u) != 0xFFFFFFFFFFFFFFFFUL ) )
{
return 1; /* error */
}
/* Store OTP structure in OTP area */
/* Clear all Flash flags before write operation*/
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
err = HAL_FLASH_Unlock( );
err |= HAL_FLASH_Program( FLASH_NSCR1_PG,
free_address, (uint32_t)&otp );
err |= HAL_FLASH_Lock( );
return err;
}
/*****************************************************************************/

View File

@@ -0,0 +1,196 @@
/**
******************************************************************************
* @file hw_pka.c
* @author MCD Application Team
* @brief This file contains the PKA driver for STM32WBA
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "app_common.h"
#include "stm32wbaxx_ll_bus.h"
#include "stm32wbaxx_ll_pka.h"
/*****************************************************************************/
extern void Error_Handler(void);
/*****************************************************************************/
typedef struct
{
uint8_t run;
} HW_PKA_VAR_T;
/*****************************************************************************/
static HW_PKA_VAR_T HW_PKA_var;
/*****************************************************************************/
__WEAK int PKA_MutexTake(void)
{
return 0; /* This shall be implemented by user */
}
__WEAK int PKA_MutexRelease(void)
{
return 0; /* This shall be implemented by user */
}
/*****************************************************************************/
int HW_PKA_Enable( void )
{
HW_PKA_VAR_T* pv = &HW_PKA_var;
/* Test if the driver is not already in use */
if ( pv->run )
{
return FALSE;
}
if (0 != PKA_MutexTake())
{
return FALSE;
}
pv->run = TRUE;
/* Enable the RNG clock as it is needed.
* See PKA chapter in IUM: the RNG peripheral must be clocked.
*/
HW_RNG_EnableClock( 2 );
UTILS_ENTER_CRITICAL_SECTION( );
/* Enable the PKA clock */
LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_PKA );
UTILS_EXIT_CRITICAL_SECTION( );
/* Enable the PKA block */
LL_PKA_Enable( PKA );
/* Wait for PKA initialization OK */
while ( !(PKA->SR & PKA_SR_INITOK) );
/* Reset any pending flag */
SET_BIT(PKA->CLRFR, (PKA_CLRFR_PROCENDFC | PKA_CLRFR_RAMERRFC |
PKA_CLRFR_ADDRERRFC | PKA_CLRFR_OPERRFC));
/* Disable the RNG clock as it is no more needed ???
*/
HW_RNG_DisableClock( 2 );
return TRUE;
}
/*****************************************************************************/
void HW_PKA_WriteSingleInput( uint32_t index, uint32_t word )
{
/* Write the single word into PKA RAM */
PKA->RAM[index] = word;
}
/*****************************************************************************/
void HW_PKA_WriteOperand( uint32_t index, int size, const uint32_t* in )
{
uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
/* Write the input data into PKA RAM */
for ( ; size > 0; size-- )
{
*pka_ram++ = *in++;
}
/* Write extra zeros into PKA RAM */
*pka_ram = 0;
}
/*****************************************************************************/
void HW_PKA_Start( uint32_t mode )
{
/* Set the configuration */
LL_PKA_Config( PKA, mode );
/* Start the PKA processing */
LL_PKA_ClearFlag_PROCEND( PKA );
LL_PKA_Start( PKA );
}
/*****************************************************************************/
int HW_PKA_EndOfOperation( void )
{
/* Return 0 if the processing is still active */
return LL_PKA_IsActiveFlag_PROCEND( PKA );
}
/*****************************************************************************/
uint32_t HW_PKA_ReadSingleOutput( uint32_t index )
{
/* Read a single word from PKA RAM */
return PKA->RAM[index];
}
/*****************************************************************************/
void HW_PKA_ReadResult( uint32_t index, int size, uint32_t* out )
{
uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
/* Read from PKA RAM */
for ( ; size > 0; size-- )
{
*out++ = *pka_ram++;
}
}
/*****************************************************************************/
void HW_PKA_Disable( void )
{
HW_PKA_VAR_T* pv = &HW_PKA_var;
if ( pv->run )
{
/* Disable the PKA block */
LL_PKA_Disable( PKA );
UTILS_ENTER_CRITICAL_SECTION( );
/* Disable the PKA clock */
LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_PKA );
UTILS_EXIT_CRITICAL_SECTION( );
if (0 != PKA_MutexRelease())
{
Error_Handler();
}
pv->run = FALSE;
}
}
/*****************************************************************************/

View File

@@ -0,0 +1,235 @@
/**
******************************************************************************
* @file hw_pka_p256.c
* @author MCD Application Team
* @brief This file is an optional part of the PKA driver for STM32WBA.
* It is dedicated to the P256 elliptic curve.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "app_common.h"
#include "stm32wbaxx_ll_pka.h"
/*****************************************************************************/
static const uint32_t HW_PKA_P256_gfp[8] =
{
0xFFFFFFFF, /* LSB */
0xFFFFFFFF,
0xFFFFFFFF,
0x00000000,
0x00000000,
0x00000000,
0x00000001,
0xFFFFFFFF,
};
static const uint32_t HW_PKA_P256_r2[8] =
{
0x00000002, /* LSB */
0x00000005,
0x00000003,
0xFFFFFFFE,
0xFFFFFFF9,
0xFFFFFFFB,
0xFFFFFFFC,
0xFFFFFFFC,
};
static const uint32_t HW_PKA_P256_p_x[8] =
{
0xD898C296, /* LSB */
0xF4A13945,
0x2DEB33A0,
0x77037D81,
0x63A440F2,
0xF8BCE6E5,
0xE12C4247,
0x6B17D1F2,
};
static const uint32_t HW_PKA_P256_p_y[8] =
{
0x37BF51F5, /* LSB */
0xCBB64068,
0x6B315ECE,
0x2BCE3357,
0x7C0F9E16,
0x8EE7EB4A,
0xFE1A7F9B,
0x4FE342E2,
};
static const uint32_t HW_PKA_P256_a[8] =
{
0x00000003, /* LSB */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
};
static const uint32_t HW_PKA_P256_b[8] =
{
0x27D2604B, /* LSB */
0x3BCE3C3E,
0xCC53B0F6,
0x651D06B0,
0x769886BC,
0xB3EBBD55,
0xAA3A93E7,
0x5AC635D8,
};
static const uint32_t HW_PKA_P256_n[8] =
{
0XFC632551, /* LSB */
0XF3B9CAC2,
0XA7179E84,
0XBCE6FAAD,
0XFFFFFFFF,
0XFFFFFFFF,
0X00000000,
0XFFFFFFFF
};
/*****************************************************************************/
void HW_PKA_P256_StartRangeCheck( const uint32_t* coord )
{
/* Set the muber of bits of P */
HW_PKA_WriteSingleInput( PKA_COMPARISON_IN_OP_NB_BITS, 256 );
/* Set the coordinate */
HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP1, 8, coord );
/* Set the modulus value p */
HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP2, 8, HW_PKA_P256_gfp );
/* Start PKA hardware */
HW_PKA_Start( LL_PKA_MODE_COMPARISON );
}
/*****************************************************************************/
uint32_t HW_PKA_P256_IsRangeCheckOk( void )
{
return (HW_PKA_ReadSingleOutput( PKA_COMPARISON_OUT_RESULT ) == 0x916AUL);
}
/*****************************************************************************/
void HW_PKA_P256_StartPointCheck( const uint32_t* x,
const uint32_t* y )
{
/* Set the muber of bits of p */
HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_MOD_NB_BITS, 256 );
/* Set the coefficient a sign */
HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_A_COEFF_SIGN, 1 );
/* Set the coefficient |a| */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_A_COEFF, 8, HW_PKA_P256_a );
/* Set the coefficient b */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_B_COEFF, 8, HW_PKA_P256_b );
/* Set the modulus value p */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_MOD_GF, 8, HW_PKA_P256_gfp );
/* Set the point coordinate x */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_X, 8, x );
/* Set the point coordinate y */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_Y, 8, y );
/* Set the Montgomery parameter */
HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_MONTGOMERY_PARAM,
8, HW_PKA_P256_r2 );
/* Start PKA hardware */
HW_PKA_Start( LL_PKA_MODE_POINT_CHECK );
}
/*****************************************************************************/
uint32_t HW_PKA_P256_IsPointCheckOk( void )
{
return (HW_PKA_ReadSingleOutput( PKA_POINT_CHECK_OUT_ERROR ) == 0xD60DUL);
}
/*****************************************************************************/
void HW_PKA_P256_StartEccScalarMul( const uint32_t* k,
const uint32_t* p_x,
const uint32_t* p_y )
{
/* Set the scalar multiplier k length */
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_EXP_NB_BITS, 256 );
/* Set the modulus length */
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS, 256 );
/* Set the coefficient a sign */
HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_A_COEFF_SIGN, 1 );
/* Set the coefficient |a| */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_A_COEFF, 8, HW_PKA_P256_a );
/* Set the coefficient b */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_B_COEFF, 8, HW_PKA_P256_b );
/* Set the modulus value p */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_MOD_GF, 8, HW_PKA_P256_gfp );
/* Set the scalar multiplier k */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_K, 8, k );
/* Set the point P coordinate x */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_X,
8, p_x ? p_x : HW_PKA_P256_p_x );
/* Set the point P coordinate y */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_Y,
8, p_y ? p_y : HW_PKA_P256_p_y );
/* Set the prime order n */
HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_N_PRIME_ORDER,
8, HW_PKA_P256_n );
/* Start PKA hardware */
HW_PKA_Start( LL_PKA_MODE_ECC_MUL );
}
/*****************************************************************************/
void HW_PKA_P256_ReadEccScalarMul( uint32_t* p_x,
uint32_t* p_y )
{
/* Read the output point X */
if ( p_x )
{
HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_X, 8, p_x );
}
/* Read the output point Y as the second half of the result */
if ( p_y )
{
HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_Y, 8, p_y );
}
}
/*****************************************************************************/

View File

@@ -0,0 +1,388 @@
/**
******************************************************************************
* @file hw_rng.c
* @author MCD Application Team
* @brief This file contains the RNG driver for STM32WBA
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "app_common.h"
#include "stm32wbaxx_ll_bus.h"
#include "stm32wbaxx_ll_rng.h"
#include "RTDebug.h"
/*****************************************************************************/
extern void Error_Handler(void);
/*****************************************************************************/
__WEAK int RNG_MutexTake(void)
{
return 0; /* This shall be implemented by user */
}
__WEAK int RNG_MutexRelease(void)
{
return 0; /* This shall be implemented by user */
}
/*****************************************************************************/
__weak void RNG_KERNEL_CLK_ON(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the RNG_KERNEL_CLK_ON could be implemented in the user file
*/
LL_RCC_HSI_Enable();
while(LL_RCC_HSI_IsReady() == 0)
{
LL_RCC_HSI_Enable();
}
}
__weak void RNG_KERNEL_CLK_OFF(void)
{
/* NOTE : This function should not be modified, when the callback is needed,
the RNG_KERNEL_CLK_OFF could be implemented in the user file
*/
}
/*****************************************************************************/
typedef struct
{
uint32_t pool[HW_RNG_POOL_SIZE];
uint8_t size;
uint8_t run;
uint8_t clock_en;
int error;
} HW_RNG_VAR_T;
/*****************************************************************************/
static HW_RNG_VAR_T HW_RNG_var;
static uint8_t hw_rng_pool_threshold = HW_RNG_POOL_DEFAULT_THRESHOLD;
/*****************************************************************************/
static void HW_RNG_WaitingClockSynchronization( void );
/*****************************************************************************/
void HW_RNG_Disable( void )
{
SYSTEM_DEBUG_SIGNAL_SET(RNG_DISABLE);
LL_RNG_Disable( RNG );
/* Disable RNG clocks */
HW_RNG_DisableClock( 1 );
SYSTEM_DEBUG_SIGNAL_RESET(RNG_DISABLE);
}
/*****************************************************************************/
void HW_RNG_EnableClock( uint8_t user_mask )
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
RNG_KERNEL_CLK_ON();
UTILS_ENTER_CRITICAL_SECTION( );
if ( pv->clock_en == 0 )
{
LL_AHB2_GRP1_EnableClock( LL_AHB2_GRP1_PERIPH_RNG );
}
pv->clock_en |= user_mask;
UTILS_EXIT_CRITICAL_SECTION( );
}
/*****************************************************************************/
void HW_RNG_DisableClock( uint8_t user_mask )
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
{
UTILS_ENTER_CRITICAL_SECTION( );
pv->clock_en &= ~user_mask;
UTILS_EXIT_CRITICAL_SECTION( );
}
/* It does not matter much if the temporisation is executed even though
* in the meantime pv->clock_en has been updated and is not more equal to 0
*/
if ( pv->clock_en == 0 )
{
HW_RNG_WaitingClockSynchronization( );
}
{
UTILS_ENTER_CRITICAL_SECTION( );
if ( pv->clock_en == 0 )
{
LL_AHB2_GRP1_DisableClock( LL_AHB2_GRP1_PERIPH_RNG );
}
UTILS_EXIT_CRITICAL_SECTION( );
}
RNG_KERNEL_CLK_OFF();
}
/*****************************************************************************/
/*
* Wait for 2 RNG kernel clock.
* Loop is sized with worst case : RNG kernel clock = 32Khz
*/
static void HW_RNG_WaitingClockSynchronization( void )
{
/* RNG busy flag is not available in STM32WBA5xxx */
#if defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx)
volatile unsigned int cpt;
for(cpt = 178 ; cpt!=0 ; --cpt);
#else
/* wait until RNG_SR_BUSY (bit 4) is cleared */
while(RNG->SR & (1 << 4));
#endif /* defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx) */
}
/*****************************************************************************/
/*
* HW_RNG_Run: this function must be called in loop.
* It implenments a simple state machine that enables the RNG,
* fills the pool with generated random numbers and then disables the RNG.
* It always returns 0 in normal conditions. In error conditions, it returns
* an error code different from 0.
*/
static int HW_RNG_Run(HW_RNG_VAR_T* pv)
{
int i, error = HW_OK;
/* check for RNG clock error */
if (LL_RNG_IsActiveFlag_CECS(RNG))
{
/* Clear RNG clock error interrupt status flags */
LL_RNG_ClearFlag_CEIS(RNG);
error = HW_RNG_CLOCK_ERROR;
}
/* check for RNG seed error */
if (LL_RNG_IsActiveFlag_SEIS(RNG))
{
/* Clear RNG seed error interrupt status flags */
LL_RNG_ClearFlag_SEIS(RNG);
/* Discard 12 words from RNG_DR in order to clean the pipeline */
for ( i = 12; i > 0; i-- )
{
LL_RNG_ReadRandData32(RNG);
}
error = HW_RNG_NOISE_ERROR;
}
/* if the pool is not full, read the H/W generated values until the pool is full */
UTILS_ENTER_CRITICAL_SECTION();
SYSTEM_DEBUG_SIGNAL_SET(RNG_GEN_RAND_NUM);
while (pv->size < HW_RNG_POOL_SIZE)
{
if (LL_RNG_IsActiveFlag_DRDY(RNG))
{
pv->pool[pv->size] = LL_RNG_ReadRandData32(RNG);
pv->size++;
}
}
SYSTEM_DEBUG_SIGNAL_RESET(RNG_GEN_RAND_NUM);
UTILS_EXIT_CRITICAL_SECTION( );
/* pool is full, disable the RNG and its RCC clock */
HW_RNG_Disable( );
/* Reset flag indicating that the RNG is ON */
pv->run = FALSE;
return error;
}
/*****************************************************************************/
void HW_RNG_Start( void )
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
/* Reset global variables */
pv->size = 0;
pv->run = FALSE;
pv->error = HW_OK;
pv->clock_en = 0;
if (0 != RNG_MutexTake())
{
Error_Handler();
}
/* Fill the random numbers pool by calling the "run" function */
do
{
pv->error = HW_RNG_Run( pv );
}
while ( pv->run && !pv->error );
if (0 != RNG_MutexRelease())
{
Error_Handler();
}
}
/*****************************************************************************/
void HW_RNG_Get( uint8_t n, uint32_t* val )
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
uint32_t pool_value;
while ( n-- )
{
UTILS_ENTER_CRITICAL_SECTION( );
if ( pv->size == 0 )
{
pv->error = HW_RNG_UFLOW_ERROR;
pool_value = ~pv->pool[HW_RNG_POOL_SIZE - n];
}
else
{
pool_value = pv->pool[--pv->size];
}
UTILS_EXIT_CRITICAL_SECTION( );
*val++ = pool_value;
}
/* Call the process callback function to fill the pool offline */
HWCB_RNG_Process( );
}
/*****************************************************************************/
int HW_RNG_Process( void )
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
int status = HW_OK;
if (0 != RNG_MutexTake())
{
status = HW_BUSY;
}
else
{
/* Check if the process is not done or if the pool is not full */
if (pv->size < hw_rng_pool_threshold)
{
HW_RNG_Init();
UTILS_ENTER_CRITICAL_SECTION( );
/* Check if an error occurred during a previous call to HW_RNG API */
status = pv->error;
pv->error = HW_OK;
UTILS_EXIT_CRITICAL_SECTION( );
if ( status == HW_OK )
{
/* Call the "run" function that generates random data */
status = HW_RNG_Run( pv );
/* If the process is not done, return "busy" status */
if ( (status == HW_OK) && pv->run )
{
status = HW_BUSY;
}
}
}
if (0 != RNG_MutexRelease())
{
Error_Handler();
}
}
if (status != HW_OK)
{
HWCB_RNG_Process( );
}
/* Return status */
return status;
}
void HW_RNG_Init(void)
{
HW_RNG_VAR_T* pv = &HW_RNG_var;
SYSTEM_DEBUG_SIGNAL_SET(RNG_ENABLE);
LL_RCC_SetRNGClockSource(LL_RCC_RNG_CLKSOURCE_HSI);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_RNG);
LL_RNG_Disable(RNG);
while(LL_RNG_IsEnabled(RNG));
/* Recommended value for NIST compliance, refer to application note AN4230 */
/* Using LL macros to set these values is not convenient as it's split
in 3 parts and need some bit polling at each step to check completion.
So, for efficiency, register direct access */
WRITE_REG(RNG->CR, RNG_CR_NIST_VALUE | RNG_CR_CONDRST | RNG_CED_DISABLE);
/* Recommended value for NIST compliance, refer to application note AN4230 */
LL_RNG_DisableClkErrorDetect(RNG);
LL_RNG_DisableCondReset(RNG);
#if !(defined(STM32WBA52xx) || defined(STM32WBA54xx) || defined(STM32WBA55xx) || defined(STM32WBA5Mxx))
while((RNG->SR & (1 << 4)));
#endif
while(LL_RNG_IsEnabledCondReset(RNG));
LL_RNG_SetHealthConfig(RNG,RNG_HTCR_NIST_VALUE);
LL_RNG_Enable(RNG);
while(!LL_RNG_IsActiveFlag_DRDY(RNG)); /*wait for data to be ready*/
pv->run = TRUE;
SYSTEM_DEBUG_SIGNAL_RESET(RNG_ENABLE);
}
void HW_RNG_SetPoolThreshold(uint8_t threshold)
{
if(threshold < HW_RNG_POOL_SIZE)
{
hw_rng_pool_threshold = threshold;
}
}

View File

@@ -0,0 +1,352 @@
/**
******************************************************************************
* @file timer_if.c
* @author MCD Application Team
* @brief Configure RTC Alarm, Tick and Calendar manager
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <math.h>
#include "stm32wbaxx_hal.h"
#include "stm32wbaxx_hal_conf.h"
#include "stm32wbaxx_ll_rtc.h"
#include "timer_if.h"
/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/**
* @brief Minimum timeout delay of Alarm in ticks
*/
#define MIN_ALARM_DELAY 3
/**
* @brief Backup seconds register
*/
#define RTC_BKP_SECONDS RTC_BKP_DR0
/**
* @brief Backup subseconds register
*/
#define RTC_BKP_SUBSECONDS RTC_BKP_DR1
/**
* @brief Backup msbticks register
*/
#define RTC_BKP_MSBTICKS RTC_BKP_DR2
/* #define RTIF_DEBUG */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/**
* @brief Timer driver callbacks handler
*/
const UTIL_TIMER_Driver_s UTIL_TimerDriver =
{
TIMER_IF_Init,
NULL,
TIMER_IF_StartTimer,
TIMER_IF_StopTimer,
TIMER_IF_SetTimerContext,
TIMER_IF_GetTimerContext,
TIMER_IF_GetTimerElapsedTime,
TIMER_IF_GetTimerValue,
TIMER_IF_GetMinimumTimeout,
TIMER_IF_Convert_ms2Tick,
TIMER_IF_Convert_Tick2ms,
};
/**
* @brief SysTime driver callbacks handler
*/
const UTIL_SYSTIM_Driver_s UTIL_SYSTIMDriver =
{
TIMER_IF_BkUp_Write_Seconds,
TIMER_IF_BkUp_Read_Seconds,
TIMER_IF_BkUp_Write_SubSeconds,
TIMER_IF_BkUp_Read_SubSeconds,
TIMER_IF_GetTime,
};
/* External variables --------------------------------------------------------*/
/**
* @brief RTC handle
*/
extern RTC_HandleTypeDef hrtc;
/* Private variables ---------------------------------------------------------*/
/**
* @brief Indicates if the RTC is already Initialized or not
*/
static bool RTC_Initialized = 0;
/**
* @brief RtcTimerContext
*/
static uint32_t RtcTimerContext = 0;
/* Exported macro ------------------------------------------------------------*/
#ifdef RTIF_DEBUG
#include "sys_app.h" /*for app_log*/
/**
* @brief Post the RTC log string format to the circular queue for printing in using the polling mode
*/
#define TIMER_IF_DBG_PRINTF(...) do{ {UTIL_ADV_TRACE_COND_FSend(VLEVEL_ALWAYS, T_REG_OFF, TS_OFF, __VA_ARGS__);} }while(0);
#else
/**
* @brief not used
*/
#define TIMER_IF_DBG_PRINTF(...)
#endif /* RTIF_DEBUG */
/* Private function prototypes -----------------------------------------------*/
/**
* @brief Get rtc timer Value in rtc tick
* @return val the rtc timer value (upcounting)
*/
static inline uint32_t GetTimerTicks(void);
/**
* @brief Writes MSBticks to backup register
* Absolute RTC time in tick is (MSBticks)<<32 + (32bits binary counter)
* @note MSBticks incremented every time the 32bits RTC timer wraps around (~44days)
* @param[in] MSBticks
* @return none
*/
static void TIMER_IF_BkUp_Write_MSBticks(uint32_t MSBticks);
/**
* @brief Reads MSBticks from backup register
* Absolute RTC time in tick is (MSBticks)<<32 + (32bits binary counter)
* @note MSBticks incremented every time the 32bits RTC timer wraps around (~44days)
* @retval MSBticks
*/
static uint32_t TIMER_IF_BkUp_Read_MSBticks(void);
/* Private user code ---------------------------------------------------------*/
UTIL_TIMER_Status_t TIMER_IF_Init(void)
{
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
if (RTC_Initialized == false)
{
/* Stop Timer */
TIMER_IF_StopTimer();
/* DeActivate the Alarm A enabled by MX during MX_RTC_Init() */
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
/* Enable Direct Read of the calendar registers (not through Shadow) */
HAL_RTCEx_EnableBypassShadow(&hrtc);
/* Initialise MSB ticks */
TIMER_IF_BkUp_Write_MSBticks(0);
TIMER_IF_SetTimerContext();
RTC_Initialized = true;
}
return ret;
}
UTIL_TIMER_Status_t TIMER_IF_StartTimer(uint32_t timeout)
{
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
RTC_AlarmTypeDef sAlarm = {0};
/* Stop timer if one is already started */
TIMER_IF_StopTimer();
timeout += RtcTimerContext;
TIMER_IF_DBG_PRINTF("Start timer: time=%d, alarm=%d\n\r", GetTimerTicks(), timeout);
/* Starts timer */
sAlarm.BinaryAutoClr = RTC_ALARMSUBSECONDBIN_AUTOCLR_NO;
sAlarm.AlarmTime.SubSeconds = UINT32_MAX - timeout;
sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDBINMASK_NONE;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
/* Initialization Error */
while(1);
}
return ret;
}
UTIL_TIMER_Status_t TIMER_IF_StopTimer(void)
{
UTIL_TIMER_Status_t ret = UTIL_TIMER_OK;
/* Clear RTC Alarm Flag */
__HAL_RTC_ALARM_CLEAR_FLAG(&hrtc, RTC_FLAG_ALRAF);
/* Disable the Alarm A interrupt */
HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
return ret;
}
uint32_t TIMER_IF_SetTimerContext(void)
{
/* Store time context */
RtcTimerContext = GetTimerTicks();
TIMER_IF_DBG_PRINTF("TIMER_IF_SetTimerContext=%d\n\r", RtcTimerContext);
/* Return time context */
return RtcTimerContext;
}
uint32_t TIMER_IF_GetTimerContext(void)
{
TIMER_IF_DBG_PRINTF("TIMER_IF_GetTimerContext=%d\n\r", RtcTimerContext);
/* Return time context */
return RtcTimerContext;
}
uint32_t TIMER_IF_GetTimerElapsedTime(void)
{
return ((uint32_t)(GetTimerTicks() - RtcTimerContext));
}
uint32_t TIMER_IF_GetTimerValue(void)
{
if (RTC_Initialized == true)
{
return GetTimerTicks();
}
else
{
return 0;
}
}
uint32_t TIMER_IF_GetMinimumTimeout(void)
{
return (MIN_ALARM_DELAY);
}
uint32_t TIMER_IF_Convert_ms2Tick(uint32_t timeMilliSec)
{
return ((uint32_t)( ( ( (uint64_t) timeMilliSec ) << RTC_N_PREDIV_S ) / 1000U ) );
}
uint32_t TIMER_IF_Convert_Tick2ms(uint32_t tick)
{
return ((uint32_t)( ( ( ( int64_t)( tick ) ) * 1000U ) >> RTC_N_PREDIV_S ) );
}
void TIMER_IF_DelayMs(uint32_t delay)
{
uint32_t delayTicks = TIMER_IF_Convert_ms2Tick(delay);
uint32_t timeout = GetTimerTicks();
/* Wait delay ms */
while (((GetTimerTicks() - timeout)) < delayTicks)
{
__NOP();
}
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
UTIL_TIMER_IRQ_Handler();
}
void HAL_RTCEx_SSRUEventCallback(RTC_HandleTypeDef *hrtc)
{
/* Called every 48 days with 1024 ticks per seconds */
TIMER_IF_DBG_PRINTF(">>Handler SSRUnderflow at %d\n\r", GetTimerTicks());
/* Increment MSBticks */
uint32_t MSB_ticks = TIMER_IF_BkUp_Read_MSBticks();
TIMER_IF_BkUp_Write_MSBticks(MSB_ticks + 1);
}
uint32_t TIMER_IF_GetTime(uint16_t *mSeconds)
{
uint64_t ticks;
uint32_t timerValueLsb = GetTimerTicks();
uint32_t timerValueMSB = TIMER_IF_BkUp_Read_MSBticks();
ticks = (((uint64_t) timerValueMSB) << 32) + timerValueLsb;
uint32_t seconds = (uint32_t)(ticks >> RTC_N_PREDIV_S);
ticks = (uint32_t) ticks & RTC_PREDIV_S;
*mSeconds = TIMER_IF_Convert_Tick2ms(ticks);
return seconds;
}
void TIMER_IF_BkUp_Write_Seconds(uint32_t Seconds)
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_SECONDS, Seconds);
}
void TIMER_IF_BkUp_Write_SubSeconds(uint32_t SubSeconds)
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_SUBSECONDS, SubSeconds);
}
uint32_t TIMER_IF_BkUp_Read_Seconds(void)
{
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_SECONDS);
}
uint32_t TIMER_IF_BkUp_Read_SubSeconds(void)
{
return HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_SUBSECONDS);
}
static void TIMER_IF_BkUp_Write_MSBticks(uint32_t MSBticks)
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_MSBTICKS, MSBticks);
}
static uint32_t TIMER_IF_BkUp_Read_MSBticks(void)
{
uint32_t MSBticks;
MSBticks = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_MSBTICKS);
return MSBticks;
}
static inline uint32_t GetTimerTicks(void)
{
uint32_t ssr = LL_RTC_TIME_GetSubSecond(RTC);
/* read twice to make sure value it valid*/
while (ssr != LL_RTC_TIME_GetSubSecond(RTC))
{
ssr = LL_RTC_TIME_GetSubSecond(RTC);
}
return UINT32_MAX - ssr;
}

View File

@@ -0,0 +1,162 @@
/**
******************************************************************************
* @file timer_if.h
* @author MCD Application Team
* @brief configuration of the timer_if.c instances
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef TIMER_IF_H
#define TIMER_IF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32_timer.h"
#include "stm32_systime.h"
/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define RTC_N_PREDIV_S (10U)
#define RTC_PREDIV_S ( ( 1U << RTC_N_PREDIV_S ) - 1U )
#define RTC_PREDIV_A ( ( 1U << ( 15U - RTC_N_PREDIV_S ) ) - 1U )
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Init RTC hardware
* @return Status based on @ref UTIL_TIMER_Status_t
*/
UTIL_TIMER_Status_t TIMER_IF_Init(void);
/**
* @brief Set the alarm
* @note The alarm is set at timeout from timer Reference (TimerContext)
* @param timeout Duration of the Timer in ticks
* @return Status based on @ref UTIL_TIMER_Status_t
*/
UTIL_TIMER_Status_t TIMER_IF_StartTimer(uint32_t timeout);
/**
* @brief Stop the Alarm
* @return Status based on @ref UTIL_TIMER_Status_t
*/
UTIL_TIMER_Status_t TIMER_IF_StopTimer(void);
/**
* @brief set timer Reference (TimerContext)
* @return Timer Reference Value in Ticks
*/
uint32_t TIMER_IF_SetTimerContext(void);
/**
* @brief Get the RTC timer Reference
* @return Timer Value in Ticks
*/
uint32_t TIMER_IF_GetTimerContext(void);
/**
* @brief Get the timer elapsed time since timer Reference (TimerContext) was set
* @return RTC Elapsed time in ticks
*/
uint32_t TIMER_IF_GetTimerElapsedTime(void);
/**
* @brief Get the timer value
* @return RTC Timer value in ticks
*/
uint32_t TIMER_IF_GetTimerValue(void);
/**
* @brief Return the minimum timeout in ticks the RTC is able to handle
* @return minimum value for a timeout in ticks
*/
uint32_t TIMER_IF_GetMinimumTimeout(void);
/**
* @brief a delay of delay ms by polling RTC
* @param delay in ms
*/
void TIMER_IF_DelayMs(uint32_t delay);
/**
* @brief converts time in ms to time in ticks
* @param[in] timeMilliSec time in milliseconds
* @return time in timer ticks
*/
uint32_t TIMER_IF_Convert_ms2Tick(uint32_t timeMilliSec);
/**
* @brief converts time in ticks to time in ms
* @param[in] tick time in timer ticks
* @return time in timer milliseconds
*/
uint32_t TIMER_IF_Convert_Tick2ms(uint32_t tick);
/**
* @brief Get rtc time
* @param[out] subSeconds in ticks
* @return time seconds
*/
uint32_t TIMER_IF_GetTime(uint16_t *subSeconds);
/**
* @brief write seconds in backUp register
* @note Used to store seconds difference between RTC time and Unix time
* @param[in] Seconds time in seconds
*/
void TIMER_IF_BkUp_Write_Seconds(uint32_t Seconds);
/**
* @brief reads seconds from backUp register
* @note Used to store seconds difference between RTC time and Unix time
* @return Time in seconds
*/
uint32_t TIMER_IF_BkUp_Read_Seconds(void);
/**
* @brief writes SubSeconds in backUp register
* @note Used to store SubSeconds difference between RTC time and Unix time
* @param[in] SubSeconds time in SubSeconds
*/
void TIMER_IF_BkUp_Write_SubSeconds(uint32_t SubSeconds);
/**
* @brief reads SubSeconds from backUp register
* @note Used to store SubSeconds difference between RTC time and Unix time
* @return Time in SubSeconds
*/
uint32_t TIMER_IF_BkUp_Read_SubSeconds(void);
#ifdef __cplusplus
}
#endif
#endif /* TIMER_IF_H */

View File

@@ -0,0 +1,81 @@
/**
******************************************************************************
* @file baes.h
* @author MCD Application Team
* @brief This file contains the interface of the basic AES software module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef BAES_H__
#define BAES_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/* Basic AES module dedicated to BLE stack with the following features:
* - AES ECB encryption
* - AES CMAC computation
*
* Configuration: the file "app_common.h" is included in this module.
* It must define:
* - CFG_BAES_SW equals to 1 for software implementation
* - CFG_BAES_SW equals to 0 for use of hardware accelerator
*
* Notes:
* - only 128-bit key is supported
* - re-entrance is not supported
*/
/* General interface */
extern void BAES_Reset( void );
/* AES ECB interface */
extern void BAES_EcbCrypt( const uint8_t* key,
const uint8_t* input,
uint8_t* output,
int enc );
/* AES CMAC interface */
extern void BAES_CmacSetKey( const uint8_t* key );
extern void BAES_CmacSetVector( const uint8_t * pIV );
extern void BAES_CmacCompute( const uint8_t* input,
uint32_t size,
uint8_t* output );
/* AES CCM interface */
extern int BAES_CcmCrypt( uint8_t mode,
const uint8_t* key,
uint8_t iv_length,
const uint8_t* iv,
uint16_t add_length,
const uint8_t* add,
uint16_t input_length,
const uint8_t* input,
uint8_t tag_length,
uint8_t* tag,
uint8_t* output );
#ifdef __cplusplus
}
#endif
#endif /* BAES_H__ */

View File

@@ -0,0 +1,120 @@
/*****************************************************************************
* @file baes_ccm.c
*
* @brief This file contains the AES CCM implementation.
*****************************************************************************
* @attention
*
* Copyright (c) 2018-2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
*****************************************************************************
*/
#include "baes_global.h"
/*****************************************************************************/
/* ---------------------------------------------------------------------------
* Byte/word manipulation macro definitions
* ---------------------------------------------------------------------------
*/
/* Returns the least significant byte from a word */
#define BYTE0(w) ((uint8_t)((w) >> 0))
/* Returns the second least significant byte from a word */
#define BYTE1(w) ((uint8_t)((w) >> 8))
/* Macro to set a 16-bit word into a byte table in big endian */
#define SET_U16_BE( b, i, v ) M_BEGIN uint16_t v_ = (uint16_t)(v); \
uint8_t *b_ = &((uint8_t*)(b))[i]; \
b_[1] = BYTE0(v_); \
b_[0] = BYTE1(v_); M_END
int BAES_CcmCrypt( uint8_t mode,
const uint8_t* key,
uint8_t iv_length,
const uint8_t* iv,
uint16_t add_length,
const uint8_t* add,
uint16_t input_length,
const uint8_t* input,
uint8_t tag_length,
uint8_t* tag,
uint8_t* output )
{
#if CFG_BAES_SW == 0
/* This implementation of AES CCM only supports HW AES and it also only
* supports the following range for input parameters:
* - tag_length: 4..16 (multiple of 2)
* - iv_length: 7..13
* - add_length: 1..14
*/
uint32_t left_len, b0[4], bx[4];
uint8_t len, *b;
/* Build B0 */
b = (uint8_t*)b0;
memset( b0, 0, 16 );
b[0] = (1U << 6) | (((tag_length - 2) / 2) << 3) | (14U - iv_length);
memcpy( b + 1, iv, iv_length );
SET_U16_BE( b, 14, input_length );
/* Build B1 */
b = (uint8_t*)bx;
memset( bx, 0, 16 );
b[1] = add_length;
memcpy( b + 2, add, add_length );
/* Start CCM process with Init and Header phases */
HW_AES_Enable( );
HW_AES_InitCcm( mode, key, b0, bx );
/* Continue CCM process with Payload Phase */
left_len = input_length;
while ( left_len > 0 )
{
len = 16;
if ( left_len < 16 )
{
len = (uint8_t)left_len;
memset( bx, 0, 16 );
if ( mode )
HW_AES_SetLast( len );
}
memcpy( b, input, len );
HW_AES_Crypt( bx, bx );
memcpy( output, b, len );
input += len;
output += len;
left_len -= len;
}
/* End CCM process with Final Phase */
HW_AES_EndCcm( tag_length, mode ? b : tag );
HW_AES_Disable( );
/* Verification of the tag in case of decryption */
if ( mode )
{
uint8_t diff = 0;
for ( int i = 0; i < tag_length; i++ )
diff |= tag[i] ^ b[i];
return (int)diff;
}
#endif /* CFG_BAES_SW == 0 */
return 0;
}
/*****************************************************************************/

View File

@@ -0,0 +1,213 @@
/**
******************************************************************************
* @file baes_cmac.c
* @author MCD Application Team
* @brief This file contains the AES CMAC implementation.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "baes_global.h"
/*****************************************************************************/
typedef struct
{
uint32_t iv[4]; /* Temporary result/IV */
#if CFG_BAES_SW != 0
uint32_t exp_key[44]; /* Expanded AES key */
#endif /* CFG_BAES_SW != 0 */
} BAES_CMAC_t;
/*****************************************************************************/
BAES_CMAC_t BAES_CMAC_var;
/*****************************************************************************/
/*
* AES key roll for CMAC Mode
*
*/
static void BAES_CmacKeyRoll( uint32_t* key )
{
uint32_t carry = ((key[0] >> 31) & 1) * 0x87UL;
key[0] = (key[0] << 1) | (key[1] >> 31);
key[1] = (key[1] << 1) | (key[2] >> 31);
key[2] = (key[2] << 1) | (key[3] >> 31);
key[3] = (key[3] << 1) ^ carry;
}
/*****************************************************************************/
/*
* AES ECB encryption for CMAC Mode
*
*/
static void BAES_CmacRawEncrypt( const uint32_t* input,
uint32_t* output )
{
#if CFG_BAES_SW == 0
HW_AES_Crypt( input, output );
#else /* CFG_BAES_SW != 0 */
BAES_CMAC_t *av = &BAES_CMAC_var;
BAES_RawEncrypt( input, output, av->exp_key );
#endif /* CFG_BAES_SW != 0 */
}
/*****************************************************************************/
/*
* Initialization for AES-CMAC for Authentication TAG Generation.
* Must be called each time a new CMAC has to be computed.
*/
void BAES_CmacSetKey( const uint8_t* key )
{
BAES_CMAC_t *av = &BAES_CMAC_var;
/* Initialize for ECB encoding */
#if CFG_BAES_SW == 0
HW_AES_Enable( );
HW_AES_SetKey( HW_AES_ENC, key );
#else /* CFG_BAES_SW != 0 */
uint32_t tmp[4];
memcpy( tmp, key, 16 );
BAES_COPY_REV( av->exp_key, tmp );
BAES_EncKeySchedule( av->exp_key );
#endif /* CFG_BAES_SW != 0 */
/* set IV to zero */
av->iv[0] = av->iv[1] = av->iv[2] = av->iv[3] = 0;
}
/*
* Initialization for AES-CMAC for Authentication TAG Generation.
* Must be called each time a new CMAC has to be computed.
*/
void BAES_CmacSetVector( const uint8_t * pIV )
{
BAES_CMAC_t * av = &BAES_CMAC_var;
// -- Update IV if exist else set to zero --
if ( pIV != NULL )
{ memcpy( av->iv, pIV, AES_BLOCK_SIZE_BYTE ); }
else
{ memset( av->iv, 0x00, AES_BLOCK_SIZE_BYTE ); }
}
/*****************************************************************************/
/*
* AES Encryption in CMAC Mode
*
* This function can be called multiple times with "size" multiple of 16 and
* "output" parameter set to NULL. However, in the last call to this function,
* any positive value for "size" is allowed and the "output" parameter must not
* be NULL.
*/
void BAES_CmacCompute( const uint8_t* input,
uint32_t size,
uint8_t* output )
{
BAES_CMAC_t *av = &BAES_CMAC_var;
uint32_t i;
uint32_t last_size = 0;
uint32_t tmp[4], key[4];
const uint8_t* ptr = input;
if ( output )
{
/* In case of final append, compute size of last block */
last_size = size % 16;
if ( (size != 0) && (last_size == 0) )
last_size = 16;
size -= last_size;
}
while ( size )
{
/* Load the input of all blocks but the last one
and xor data with previous tag */
memcpy( tmp, ptr, 16 );
BAES_REV_XOR( tmp, av->iv );
/* Encrypt block */
BAES_CmacRawEncrypt( tmp, av->iv );
/* Next block */
ptr += 16;
size -= 16;
}
if ( output )
{
/* Load the input bytes left with 0 padding */
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
for ( i = 0; i < last_size; i++ )
{
BAES_OR_BYTE_BE( tmp, i, ptr[i] );
}
/* Compute K1 */
key[0] = key[1] = key[2] = key[3] = 0;
BAES_CmacRawEncrypt( key, key );
BAES_CmacKeyRoll( key );
/* Add padding and compute K2 if the last block is not full */
if ( last_size < 16 )
{
BAES_OR_BYTE_BE( tmp, last_size, 0x80 );
BAES_CmacKeyRoll( key );
}
/* Xor data with previous tag and key */
for ( i = 0; i < 4; i++ )
{
tmp[i] ^= av->iv[i] ^ key[i];
}
/* Encrypt block */
BAES_CmacRawEncrypt( tmp, av->iv );
#if CFG_BAES_SW == 0
HW_AES_Disable( );
#endif /* CFG_BAES_SW == 0 */
/* Write the tag */
BAES_COPY_REV( tmp, av->iv );
memcpy( output, tmp, 16 );
}
}
/*****************************************************************************/

View File

@@ -0,0 +1,89 @@
/**
******************************************************************************
* @file baes_ecb.c
* @author MCD Application Team
* @brief This file contains the AES ECB functions implementation.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "baes_global.h"
/*****************************************************************************/
void BAES_Reset( void )
{
#if CFG_BAES_SW == 0
HW_AES_Disable( );
#endif
}
/*****************************************************************************/
void BAES_EcbCrypt( const uint8_t* key,
const uint8_t* input,
uint8_t* output,
int enc )
{
uint32_t tmp[4];
#if CFG_BAES_SW == 0
HW_AES_Enable( );
HW_AES_SetKey( (enc ? (HW_AES_ENC | HW_AES_REV) : (HW_AES_DEC | HW_AES_REV)),
key );
#else /* CFG_BAES_SW != 0 */
uint32_t exp_key[44];
/* Retrieve all bytes from key */
memcpy( exp_key, key, 16 );
BAES_SWAP( exp_key );
#if CFG_BAES_SW_DECRYPTION != 0
if ( !enc )
BAES_DecKeySchedule( exp_key );
else
#endif /* CFG_BAES_SW_DECRYPTION != 0 */
BAES_EncKeySchedule( exp_key );
#endif /* CFG_BAES_SW != 0 */
/* Retrieve all bytes from input */
memcpy( tmp, input, 16 );
BAES_SWAP( tmp );
#if CFG_BAES_SW == 0
HW_AES_Crypt( tmp, tmp );
HW_AES_Disable( );
#else /* CFG_BAES_SW != 0 */
#if CFG_BAES_SW_DECRYPTION != 0
if ( !enc )
BAES_RawDecrypt( tmp, tmp, exp_key );
else
#endif /* CFG_BAES_SW_DECRYPTION != 0 */
BAES_RawEncrypt( tmp, tmp, exp_key );
#endif /* CFG_BAES_SW != 0 */
/* Write all bytes to output */
BAES_SWAP( tmp );
memcpy( output, tmp, 16 );
}
/*****************************************************************************/

View File

@@ -0,0 +1,127 @@
/**
******************************************************************************
* @file baes_global.h
* @author MCD Application Team
* @brief This file contains the internal definitions of the AES software
* module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef BAES_GLOBAL_H__
#define BAES_GLOBAL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "app_common.h"
#include "baes.h"
/* Default software configuration */
#define AES_BLOCK_SIZE_BIT 128u /* AES Size in Bits */
#define AES_BLOCK_SIZE_BYTE 16u /* AES Size in Bytes */
#define AES_BLOCK_SIZE_WORD 4u /* AES Size in Words */
#define AES_EXPANDED_KEY_SIZE 44u
/* By default, use of AES H/W implementation instead of S/W */
#ifndef CFG_BAES_SW
#define CFG_BAES_SW 0
#endif
#if CFG_BAES_SW == 1
/* Enables to include AES S/W decryption when set to 1 */
#ifndef CFG_BAES_SW_DECRYPTION
#define CFG_BAES_SW_DECRYPTION 0
#endif
/* Choice of the AES S/W algorithm version:
* 1: slow version with 522 bytes of look-up tables
* 2: fast version with 2048 bytes of look-up tables */
#ifndef CFG_BAES_SW_ALGORITHM
#define CFG_BAES_SW_ALGORITHM 1
#endif
#endif /* CFG_BAES_SW == 1 */
/* Internal macros */
/* Reverse the words in a 4-word array */
#define BAES_SWAP( w ) \
M_BEGIN uint32_t t_; \
t_ = (w)[0]; (w)[0] = (w)[3]; (w)[3] = t_; \
t_ = (w)[1]; (w)[1] = (w)[2]; (w)[2] = t_; \
M_END
/* Reverse the bytes and words in a 4-word array */
#define BAES_SWAP_REV( w ) \
M_BEGIN uint32_t t_; \
t_ = (w)[0]; (w)[0] = __REV((w)[3]); (w)[3] = __REV(t_); \
t_ = (w)[1]; (w)[1] = __REV((w)[2]); (w)[2] = __REV(t_); \
M_END
/* Reverse the words of a 4-word array and xor the result */
#define BAES_SWAP_XOR( w, x ) \
M_BEGIN uint32_t t_; \
t_ = (w)[0]; (w)[0] = (w)[3] ^ ((x)[0]); (w)[3] = t_ ^ ((x)[3]); \
t_ = (w)[1]; (w)[1] = (w)[2] ^ ((x)[1]); (w)[2] = t_ ^ ((x)[2]); \
M_END
/* Reverse the bytes of a 4-word array and xor the result */
#define BAES_REV_XOR( w, x ) \
M_BEGIN \
(w)[0] = __REV((w)[0]) ^ ((x)[0]); (w)[1] = __REV((w)[1]) ^ ((x)[1]); \
(w)[2] = __REV((w)[2]) ^ ((x)[2]); (w)[3] = __REV((w)[3]) ^ ((x)[3]); \
M_END
/* Copy and reverse the words of a 4-word array */
#define BAES_COPY_SWAP( d, s ) \
M_BEGIN \
(d)[0] = (s)[3]; (d)[1] = (s)[2]; \
(d)[2] = (s)[1]; (d)[3] = (s)[0]; \
M_END
/* Copy and reverse the bytes of a 4-word array */
#define BAES_COPY_REV( d, s ) \
M_BEGIN \
(d)[0] = __REV((s)[0]); (d)[1] = __REV((s)[1]); \
(d)[2] = __REV((s)[2]); (d)[3] = __REV((s)[3]); \
M_END
/* Modifies a byte in a word array in Big Endian */
#define BAES_OR_BYTE_BE( w, n, b ) \
(w)[(n)/4] |= ((uint32_t)(b)) << (8 * (3-((n)%4)))
/* Note: BYTE0, BYTE1, BYTE2, BYTE3 and BTOW macros are also used
but they should be defined in "common.h" */
/* Internal functions */
extern void BAES_EncKeySchedule( uint32_t* p_exp_key );
extern void BAES_DecKeySchedule( uint32_t* p_exp_key );
extern void BAES_RawEncrypt( const uint32_t* p_in,
uint32_t* p_out,
const uint32_t *p_exp_key );
extern void BAES_RawDecrypt( const uint32_t* p_in,
uint32_t* p_out,
const uint32_t* p_exp_key );
#ifdef __cplusplus
}
#endif
#endif /* BAES_GLOBAL_H__ */

View File

@@ -0,0 +1,151 @@
/**
******************************************************************************
* @file flash_driver.c
* @author MCD Application Team
* @brief The Flash Driver module is the interface layer between Flash
* management modules and HAL Flash drivers
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "flash_driver.h"
#include "utilities_conf.h"
/* Global variables ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define FD_CTRL_NO_BIT_SET (0UL) /* value used to reset the Flash Control status */
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/**
* @brief variable used to represent the Flash Control status
*/
static volatile FD_Flash_ctrl_bm_t FD_Flash_Control_status = FD_CTRL_NO_BIT_SET;
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
/**
* @brief Update Flash Control status
* @param Flags_bm: Bit mask identifying the caller (1 bit per user)
* @param Status: Action requested (enable or disable flash access)
* @retval None
*/
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status)
{
UTILS_ENTER_CRITICAL_SECTION();
switch (Status)
{
case LL_FLASH_DISABLE:
{
FD_Flash_Control_status |= (1u << Flags_bm);
break;
}
case LL_FLASH_ENABLE:
{
FD_Flash_Control_status &= ~(1u << Flags_bm);
break;
}
default :
{
break;
}
}
UTILS_EXIT_CRITICAL_SECTION();
}
/**
* @brief Write a block of 128 bits (4 32-bit words) in Flash
* @param Dest: Address where to write in Flash (128-bit aligned)
* @param Payload: Address of data to be written in Flash (32-bit aligned)
* @retval FD_FlashOp_Status_t: Success or failure of Flash write operation
*/
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload)
{
FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;
/* Check if RFTS OR Application allow flash access */
if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
(FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
{ /* Access not allowed */
return status;
}
/* Wait for system to allow flash access */
while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, Dest, Payload) == HAL_OK)
{
status = FD_FLASHOP_SUCCESS;
}
return status;
}
/**
* @brief Erase one sector of Flash
* @param Sect: Identifier of the sector to erase
* @retval FD_FlashOp_Status_t: Success or failure of Flash erase operation
*/
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect)
{
FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;
uint32_t page_error;
FLASH_EraseInitTypeDef p_erase_init;
#ifndef FLASH_DBANK_SUPPORT
if (FLASH_PAGE_NB < Sect)
#else
if ((FLASH_PAGE_NB * 2u) < Sect)
#endif
{
return status;
}
/* Check if LL allows flash access */
if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
(FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
{ /* Access not allowed */
return status;
}
/* Wait for system to allow flash access */
while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));
p_erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
p_erase_init.Page = (Sect & (FLASH_PAGE_NB - 1u));
p_erase_init.NbPages = 1;
#if defined(FLASH_DBANK_SUPPORT)
/* Verify which Bank is impacted */
if ((FLASH_PAGE_NB <= Sect) ^ (OB_SWAP_BANK_ENABLE == READ_BIT (FLASH->OPTR, FLASH_OPTR_SWAP_BANK_Msk)))
{
p_erase_init.Banks = FLASH_BANK_2;
}
else
{
p_erase_init.Banks = FLASH_BANK_1;
}
#endif
if (HAL_FLASHEx_Erase(&p_erase_init, &page_error) == HAL_OK)
{
status = FD_FLASHOP_SUCCESS;
}
return status;
}

View File

@@ -0,0 +1,88 @@
/**
******************************************************************************
* @file flash_driver.h
* @author MCD Application Team
* @brief Header for flash_driver.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef FLASH_DRIVER_H
#define FLASH_DRIVER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
/* Exported types ------------------------------------------------------------*/
/* Bit mask to modify Flash Control status */
typedef uint32_t FD_Flash_ctrl_bm_t;
/* Flash operation status */
typedef enum
{
FD_FLASHOP_SUCCESS,
FD_FLASHOP_FAILURE
} FD_FlashOp_Status_t;
/* Flash Driver commands to enable or disable flash access */
typedef enum
{
LL_FLASH_ENABLE,
LL_FLASH_DISABLE,
} FD_FLASH_Status_t;
/**
* @brief Bit mask to modify Flash Control status
*
* @details Those bitmasks are used to enable/disable access to the flash:
* - System:
* -# FD_FLASHACCESS_SYSTEM: Determine whether or not the flash access is allowed from a system POV.
* This bit has a predominance over all the other bit masks, ie: No flash operation can
* be achieved without this to be set to 0, ie: LL_FLASH_ENABLE.
* - RFTS:
* -# FD_FLASHACCESS_RFTS: Determine whether or not the RF Timing Synchro allows flash access. This bit is set
* once a window has been allowed by the BLE LL, ie: set to 0.
* This bit has no impact when FD_FLASHACCESS_RFTS_BYPASS is set, ie: set to 0.
* -# FD_FLASHACCESS_RFTS_BYPASS: Nullify the impact of FD_FLASHACCESS_RFTS when enabled, ie: set to 0. Its role is
* to allow flash operation without the need to request a timing window to the RFTS,
* ie: Executing flash operation without the BLE LL.
*
*/
typedef enum FD_FlashAccess_bm
{
/* System flash access bitfield */
FD_FLASHACCESS_SYSTEM,
/* RF Timing Synchro flash access bitfield */
FD_FLASHACCESS_RFTS,
/* Bypass of RF Timing Synchro flash access bitfield */
FD_FLASHACCESS_RFTS_BYPASS,
}FD_FlashAccess_bm_t;
/* Exported constants --------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status);
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload);
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect);
#ifdef __cplusplus
}
#endif
#endif /*FLASH_DRIVER_H */

View File

@@ -0,0 +1,516 @@
/**
******************************************************************************
* @file flash_manager.c
* @author MCD Application Team
* @brief The Flash Manager module provides an interface to write raw data
* from SRAM to FLASH
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "flash_manager.h"
#include "rf_timing_synchro.h"
#include "flash_driver.h"
#include "utilities_conf.h"
#include "stm32wbaxx_hal.h"
/* Debug */
#include "log_module.h"
/* Global variables ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* State of the background process */
typedef enum FM_BackGround_States
{
FM_BKGND_NOWINDOW_FLASHOP,
FM_BKGND_WINDOWED_FLASHOP,
}FM_BackGround_States_t;
/* Flash operation type */
typedef enum
{
FM_WRITE_OP,
FM_ERASE_OP
} FM_FlashOp_t;
/**
* @brief Flash operation configuration struct
*/
typedef struct FM_FlashOpConfig
{
uint32_t *writeSrc;
uint32_t *writeDest;
int32_t writeSize;
uint32_t eraseFirstSect;
uint32_t eraseNbrSect;
}FM_FlashOpConfig_t;
/* Private defines -----------------------------------------------------------*/
#define FLASH_PAGE_NBR (FLASH_SIZE / FLASH_PAGE_SIZE)
#define FLASH_WRITE_BLOCK_SIZE 4U
#define ALIGNMENT_32 0x00000003
#define ALIGNMENT_128 0x0000000F
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/**
* @brief Semaphore on Flash
*/
static bool busy_flash_sem = FALSE;
/**
* @brief Indicates if the flash manager module is available or not
*/
static bool flash_manager_busy = FALSE;
/**
* @brief Parameters for Flash Write command
*/
static bool fm_window_granted = FALSE;
/**
* @brief Callback node list for pending flash operation request
*/
static tListNode fm_cb_pending_list;
/**
* @brief Pointer to current flash operation requester's callback
*/
static void (*fm_running_cb)(FM_FlashOp_Status_t);
/**
* @brief Type of current flash operation (Write/Erase)
*/
static FM_FlashOp_t fm_flashop;
/**
* @brief Parameters for Flash operation
*/
static FM_FlashOpConfig_t fm_flashop_parameters;
/**
* @brief State of the Background process
*/
static FM_BackGround_States_t FM_CurrentBackGroundState;
/* Private function prototypes -----------------------------------------------*/
static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode);
static void FM_WindowAllowed_Callback(void);
/* Functions Definition ------------------------------------------------------*/
/**
* @brief Initialize the Flash manager module
*/
void FM_Init (void)
{
static bool fm_cb_pending_list_init = false;
/* Initialize pending list if not done */
if (fm_cb_pending_list_init == false)
{
LST_init_head(&fm_cb_pending_list);
fm_cb_pending_list_init = true;
}
}
/**
* @brief Request the Flash Manager module to initiate a Flash Write operation
* @param Src: Address of the data to be stored in FLASH. It shall be 32bits aligned
* @param Dest: Address where the data shall be written. It shall be 128bits aligned
* @param Size: This is the size of data to be written in Flash.
The size is a multiple of 32bits (size = 1 means 32bits)
* @param CallbackNode: Pointer to the callback node for storage in list
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
*/
FM_Cmd_Status_t FM_Write(uint32_t *Src, uint32_t *Dest, int32_t Size, FM_CallbackNode_t *CallbackNode)
{
FM_Cmd_Status_t status;
if (((uint32_t)Dest < FLASH_BASE) || ((uint32_t)Dest > (FLASH_BASE + FLASH_SIZE))
|| (((uint32_t)Dest + Size) > (FLASH_BASE + FLASH_SIZE)))
{
LOG_ERROR_SYSTEM("\r\nFM_Write - Destination address not part of the flash");
/* Destination address not part of the flash */
return FM_ERROR;
}
if (((uint32_t) Src & ALIGNMENT_32) || ((uint32_t) Dest & ALIGNMENT_128))
{
LOG_ERROR_SYSTEM("\r\nFM_Write - Source or destination address not properly aligned");
/* Source or destination address not properly aligned */
return FM_ERROR;
}
status = FM_CheckFlashManagerState(CallbackNode);
if (status == FM_OK)
{ /* Flash manager is available */
/* Save Write parameters */
fm_flashop_parameters.writeSrc = Src;
fm_flashop_parameters.writeDest = Dest;
fm_flashop_parameters.writeSize = Size;
fm_flashop = FM_WRITE_OP;
FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;
/* Window request to be executed in background */
FM_ProcessRequest();
}
LOG_DEBUG_SYSTEM("\r\nFM_Write - Returned value : %d", status);
return status;
}
/**
* @brief Request the Flash Manager module to initiate a Flash Erase operation
* @param FirstSect: Index of the first sector to erase
* @param NbrSect: Number of sector to erase
* @param CallbackNode: Pointer to the callback node for storage in list
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
*/
FM_Cmd_Status_t FM_Erase(uint32_t FirstSect, uint32_t NbrSect, FM_CallbackNode_t *CallbackNode)
{
FM_Cmd_Status_t status;
if ((FirstSect > FLASH_PAGE_NBR) || ((FirstSect + NbrSect) > FLASH_PAGE_NBR))
{
LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");
/* Inconsistent request */
return FM_ERROR;
}
if (NbrSect == 0)
{
LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");
/* Inconsistent request */
return FM_ERROR;
}
status = FM_CheckFlashManagerState(CallbackNode);
if (status == FM_OK)
{ /* Flash manager is available */
/* Save Erase parameters */
fm_flashop_parameters.eraseFirstSect = FirstSect;
fm_flashop_parameters.eraseNbrSect = NbrSect;
fm_flashop = FM_ERASE_OP;
FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;
/* Window request to be executed in background */
FM_ProcessRequest();
}
LOG_DEBUG_SYSTEM("\r\nFM_Erase - Returned value : %d", status);
return status;
}
/**
* @brief Execute Flash Manager background tasks
* @param None
* @retval None
*/
void FM_BackgroundProcess (void)
{
static uint32_t duration;
bool flashop_complete = false;
FD_FlashOp_Status_t fdReturnValue = FD_FLASHOP_SUCCESS;
FM_CallbackNode_t *pCbNode = NULL;
switch (FM_CurrentBackGroundState)
{
case FM_BKGND_NOWINDOW_FLASHOP:
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP");
if (fm_flashop == FM_WRITE_OP)
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Write operation");
/* Update duration time value */
duration = TIME_WINDOW_WRITE_REQUEST;
/* Set the next possible state - App could stop at anytime no window operation */
FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;
HAL_FLASH_Unlock();
while((fm_flashop_parameters.writeSize > 0) &&
(fdReturnValue == FD_FLASHOP_SUCCESS))
{
fdReturnValue = FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
(uint32_t) fm_flashop_parameters.writeSrc);
if (fdReturnValue == FD_FLASHOP_SUCCESS)
{
fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
}
}
HAL_FLASH_Lock();
/* Is write over ? */
if (fm_flashop_parameters.writeSize <= 0)
{
flashop_complete = true;
}
}
else
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Erase operation");
/* Update duration time value */
duration = TIME_WINDOW_ERASE_REQUEST;
/* Set the next possible state */
FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;
HAL_FLASH_Unlock();
while((fm_flashop_parameters.eraseNbrSect > 0) &&
(fdReturnValue == FD_FLASHOP_SUCCESS))
{
fdReturnValue = FD_EraseSectors(fm_flashop_parameters.eraseFirstSect);
if (fdReturnValue == FD_FLASHOP_SUCCESS)
{
fm_flashop_parameters.eraseNbrSect--;
fm_flashop_parameters.eraseFirstSect++;
}
}
HAL_FLASH_Lock();
if (fm_flashop_parameters.eraseNbrSect == 0)
{
flashop_complete = true;
}
}
break;
}
case FM_BKGND_WINDOWED_FLASHOP:
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP");
if (fm_window_granted == false)
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - No time window granted yet, request one");
/* No time window granted yet, request one */
RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
}
else
{
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Time window granted");
if (fm_flashop == FM_WRITE_OP)
{
/* Flash Write operation */
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Write operation");
HAL_FLASH_Unlock();
while((fm_flashop_parameters.writeSize > 0) &&
(FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
(uint32_t) fm_flashop_parameters.writeSrc) == FD_FLASHOP_SUCCESS))
{
fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
}
if (fm_flashop_parameters.writeSize <= 0)
{
flashop_complete = true;
}
HAL_FLASH_Lock();
}
else
{
/* Flash Erase operation */
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Erase operation");
HAL_FLASH_Unlock();
/* Erase only one sector in a single time window */
if (FD_EraseSectors(fm_flashop_parameters.eraseFirstSect) == FD_FLASHOP_SUCCESS)
{
fm_flashop_parameters.eraseNbrSect--;
fm_flashop_parameters.eraseFirstSect++;
}
if (fm_flashop_parameters.eraseNbrSect == 0)
{
flashop_complete = true;
}
HAL_FLASH_Lock();
}
/* Release the time window */
RFTS_RelWindow();
/* Indicate that there is no more window */
fm_window_granted = false;
}
break;
}
default:
{
/* Nothing to do here */
break;
}
}
if (flashop_complete == true)
{
UTILS_ENTER_CRITICAL_SECTION();
/* Release semaphore on flash */
busy_flash_sem = false;
/* Set Flash Manager busy */
flash_manager_busy = false;
UTILS_EXIT_CRITICAL_SECTION();
/* Invoke the running callback if present */
if (fm_running_cb != NULL)
{
fm_running_cb(FM_OPERATION_COMPLETE);
}
/* notify pending requesters */
while((LST_is_empty (&fm_cb_pending_list) == false) &&
(busy_flash_sem == false) && (flash_manager_busy == false))
{
LST_remove_head (&fm_cb_pending_list, (tListNode**)&pCbNode);
pCbNode->Callback(FM_OPERATION_AVAILABLE);
}
}
else
{
/* Flash operation not complete yet */
LOG_DEBUG_SYSTEM("\r\nFM_BackgroundProcess - Flash operation not complete yet, request a new time window");
/* Request a new time window */
RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
}
}
/**
* @brief Check if the Flash Manager is busy or available
* @param CallbackNode: Pointer to the callback node for storage in list
* @retval FM_Cmd_Status_t: Status of the Flash Manager module
*/
static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode)
{
bool fm_process_cmd = false;
FM_Cmd_Status_t status = FM_ERROR;
/* Check if semaphore on flash is available */
UTILS_ENTER_CRITICAL_SECTION();
/* Check if semaphore on flash is available */
if (busy_flash_sem == false)
{ /* Check if Flash Manager is already busy */
if (flash_manager_busy == false)
{
busy_flash_sem = true; /* Get semaphore on flash */
flash_manager_busy = true; /* Set Flash Manager busy */
fm_process_cmd = true;
}
else
{
fm_process_cmd = false;
}
}
else
{
fm_process_cmd = false;
}
UTILS_EXIT_CRITICAL_SECTION();
if (fm_process_cmd == false)
{ /* Flash manager busy */
/* Append callback to the pending list */
if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
{
LST_insert_tail(&fm_cb_pending_list, &(CallbackNode->NodeList));
}
status = FM_BUSY;
}
else
{ /* Flash manager is available */
if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
{
UTILS_ENTER_CRITICAL_SECTION();
fm_running_cb = CallbackNode->Callback;
UTILS_EXIT_CRITICAL_SECTION();
}
else
{
UTILS_ENTER_CRITICAL_SECTION();
fm_running_cb = NULL;
UTILS_EXIT_CRITICAL_SECTION();
}
status = FM_OK;
}
return status;
}
/**
* @brief Callback called by RF Timing Synchro module when a time window is available
* @param None
* @retval None
*/
static void FM_WindowAllowed_Callback(void)
{
fm_window_granted = true;
LOG_DEBUG_SYSTEM("\r\nFM_WindowAllowed_Callback");
/* Flash operation to be executed in background */
FM_ProcessRequest();
}

View File

@@ -0,0 +1,79 @@
/**
******************************************************************************
* @file flash_manager.h
* @author MCD Application Team
* @brief Header for flash_manager.c module
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef FLASH_MANAGER_H
#define FLASH_MANAGER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
#include "stm_list.h"
/* Exported types ------------------------------------------------------------*/
/* Flash Manager command status */
typedef enum
{
FM_OK, /* The Flash Manager is available and a window request is scheduled */
FM_BUSY, /* The Flash Manager is busy and the caller will be called back when it is available */
FM_ERROR /* An error occurred while processing the command */
} FM_Cmd_Status_t;
/* Flash operation status */
typedef enum
{
FM_OPERATION_COMPLETE, /* The requested flash operation is complete */
FM_OPERATION_AVAILABLE /* A flash operation can be requested */
} FM_FlashOp_Status_t;
/**
* @brief Flash Manager callback node type to store them in a chained list
*/
typedef struct FM_CallbackNode
{
tListNode NodeList; /* Next and previous nodes in the list */
void (*Callback)(FM_FlashOp_Status_t Status); /* Callback function pointer for Flash Manager caller */
}FM_CallbackNode_t;
/* Exported constants --------------------------------------------------------*/
#define TIME_WINDOW_ERASE_DURATION 4000U /* Duration in us of the time window requested for Flash Erase */
#define TIME_WINDOW_WRITE_DURATION 1000U /* Duration in us of the time window requested for Flash Write */
#define TIME_WINDOW_MARGIN 100U /* Time margin added so to ensure timeout protection before actual closure */
/* As timers use ms, amount below 1000 is removed at conversion */
#define TIME_WINDOW_ERASE_REQUEST (TIME_WINDOW_ERASE_DURATION + TIME_WINDOW_MARGIN)
#define TIME_WINDOW_WRITE_REQUEST (TIME_WINDOW_WRITE_DURATION + TIME_WINDOW_MARGIN)
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void FM_Init (void);
FM_Cmd_Status_t FM_Write(uint32_t *Src, uint32_t *Dest, int32_t Size, FM_CallbackNode_t *CallbackNode);
FM_Cmd_Status_t FM_Erase(uint32_t FirstSect, uint32_t NbrSect, FM_CallbackNode_t *CallbackNode);
void FM_BackgroundProcess (void);
void FM_ProcessRequest (void);
#ifdef __cplusplus
}
#endif
#endif /*FLASH_MANAGER_H */

View File

@@ -0,0 +1,216 @@
/**
******************************************************************************
* @file rf_timing_synchro.c
* @author MCD Application Team
* @brief The RF Timing Synchronization module provides an interface to
* synchronize the flash processing versus the RF activity to make
* sure the RF timing is not broken
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "rf_timing_synchro.h"
#include "evnt_schdlr_gnrc_if.h"
#include "utilities_conf.h"
#include "stm32_timer.h"
#include "flash_driver.h"
/* Global variables ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
/**
* @brief Pointer to time window requester's callback
*/
static void (*req_callback)(void);
/**
* @brief Indicates if a time window has already been requested or not
*/
static bool rfts_window_req_pending = FALSE;
/**
* @brief Timer used by the RFTS module to prevent time window overrun
*/
static UTIL_TIMER_Object_t rfts_timer;
/**
* @brief Firmware Link Layer external event handler
*/
static ext_evnt_hndl_t ext_event_handler;
/* Private function prototypes -----------------------------------------------*/
static void RFTS_WindowAllowed_Callback(void);
static void RFTS_Timeout_Callback(void* Argument);
static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr);
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
/* Functions Definition ------------------------------------------------------*/
/**
* @brief Request a time window to the Firmware Link Layer
* @param duration: Duration in us of the time window requested
* @param Callback: Callback to be called when time window is allocated
* @retval RFTS_Cmd_Status_t: Success or failure of the window request
*/
RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void))
{
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
extrnl_evnt_st_t extrnl_evnt_config;
bool req_pending = false;
if (Callback == NULL)
{ /* Prevent use of uninitialized callback */
return RFTS_WINDOW_REQ_FAILED;
}
/* Check no request is already pending */
UTILS_ENTER_CRITICAL_SECTION();
if (rfts_window_req_pending == true)
{
req_pending = true;
}
else
{
rfts_window_req_pending = true;
}
UTILS_EXIT_CRITICAL_SECTION();
if (req_pending == true)
{ /* A window request is already pending */
return RFTS_WINDOW_REQ_FAILED;
}
/* Register requester's callback */
req_callback = Callback;
/* Submit request to Firmware Link Layer */
extrnl_evnt_config.deadline = 0;
extrnl_evnt_config.strt_min = 0;
extrnl_evnt_config.strt_max = 0;
extrnl_evnt_config.durn_min = Duration;
extrnl_evnt_config.durn_max = 0;
extrnl_evnt_config.prdc_intrvl = 0;
extrnl_evnt_config.priority = PRIORITY_DEFAULT;
extrnl_evnt_config.blocked = STATE_NOT_BLOCKED;
extrnl_evnt_config.ptr_priv = NULL;
extrnl_evnt_config.evnt_strtd_cbk = &event_started_callback;
extrnl_evnt_config.evnt_blckd_cbk = NULL;
extrnl_evnt_config.evnt_abortd_cbk = NULL;
UTIL_TIMER_Create(&rfts_timer,
(Duration/1000),
UTIL_TIMER_ONESHOT,
&RFTS_Timeout_Callback,
NULL);
ext_event_handler = evnt_schdlr_rgstr_gnrc_evnt(&extrnl_evnt_config);
if (ext_event_handler == NULL)
{
UTILS_ENTER_CRITICAL_SECTION();
rfts_window_req_pending = false;
UTILS_EXIT_CRITICAL_SECTION();
return RFTS_WINDOW_REQ_FAILED;
}
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
return RFTS_CMD_OK;
}
/**
* @brief Execute necessary tasks to allow the time window to be released
* @param None
* @retval RFTS_Cmd_Status_t: Success or error in the window release procedure
*/
RFTS_Cmd_Status_t RFTS_RelWindow(void)
{
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
RFTS_Cmd_Status_t status;
/* Stop RFTS module window overrun control timer */
UTIL_TIMER_Stop(&rfts_timer);
/* Inform Firmware Link Layer that time window can be released */
if (evnt_schdlr_gnrc_evnt_cmplt(ext_event_handler) == 0)
{
status = RFTS_CMD_OK;
}
else
{
status = RFTS_WINDOW_REL_ERROR;
}
/* Forbid flash operation */
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
UTILS_ENTER_CRITICAL_SECTION();
rfts_window_req_pending = false;
UTILS_EXIT_CRITICAL_SECTION();
return status;
#else
return RFTS_CMD_OK;
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */
}
#if (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u)
/**
* @brief Callback called by Firmware Link Layer when a time window is available
* @note This callback is supposed to be called under interrupt
* @param None
* @retval None
*/
static void RFTS_WindowAllowed_Callback(void)
{
/* Allow flash operation */
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_ENABLE);
/* Start timer preventing window overrun */
UTIL_TIMER_Start(&rfts_timer);
/* Call back requester to inform time window is available */
req_callback();
}
/**
* @brief Callback triggered by a timeout when the allocated window time is elapsed
* @note This callback is supposed to be called under interrupt
* @param None
* @retval None
*/
static void RFTS_Timeout_Callback(void* Argument)
{
/* Forbid flash operation */
FD_SetStatus(FD_FLASHACCESS_RFTS, LL_FLASH_DISABLE);
UTILS_ENTER_CRITICAL_SECTION();
rfts_window_req_pending = false;
UTILS_EXIT_CRITICAL_SECTION();
}
static uint32_t event_started_callback(ext_evnt_hndl_t evnt_hndl, uint32_t slot_durn, void* priv_data_ptr)
{
RFTS_WindowAllowed_Callback();
return 0;
}
#endif /* (DISABLE_RFTS_EXT_EVNT_HNDLR == 0u) */

View File

@@ -0,0 +1,54 @@
/**
******************************************************************************
* @file rf_timing_synchro.h
* @author MCD Application Team
* @brief Header for rf_timing_synchro.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef RF_TIMING_SYNCHRO_H
#define RF_TIMING_SYNCHRO_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
/* Exported types ------------------------------------------------------------*/
/* RFTS command status */
typedef enum
{
RFTS_CMD_OK, /* The RF Timing synchronization command was successfully executed */
RFTS_WINDOW_REQ_FAILED, /* The RF Timing synchronization module failed to register the window request */
RFTS_WINDOW_REL_ERROR /* An error occurred during the window release procedure */
} RFTS_Cmd_Status_t;
/* Exported constants --------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
RFTS_Cmd_Status_t RFTS_ReqWindow(uint32_t Duration, void (*Callback)(void));
RFTS_Cmd_Status_t RFTS_RelWindow(void);
#ifdef __cplusplus
}
#endif
#endif /*RF_TIMING_SYNCHRO_H */

View File

@@ -0,0 +1,130 @@
/**
******************************************************************************
* @file simple_nvm_arbiter.h
* @author MCD Application Team
* @brief Header for simple_nvm_arbiter.c module
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef SIMPLE_NVM_ARBITER_H
#define SIMPLE_NVM_ARBITER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "simple_nvm_arbiter_common.h"
#include "simple_nvm_arbiter_conf.h"
#include "utilities_common.h"
/* Exported constants --------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initialize the Simple NVM Arbiter
*
* @param p_NvmStartAddress: Start address of the NVM to work with - Shall be aligned 128 bits
*
* @return Status of the command
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_ALREADY_INIT
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_NULL
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_NOT_ALIGNED
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_OVERLAP_FLASH
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CRC_INIT
*/
SNVMA_Cmd_Status_t SNVMA_Init (const uint32_t * p_NvmStartAddress);
/**
* @brief Register a user buffer to a NVM
*
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
*
* @param BufferId: Id of the user which ask for buffer registration
* @param p_BufferAddress: Address of the buffer to be registered - Shall be aligned 32 bits
* @param BufferSize: Size of the buffer to be registered - Shall be a multiple of 32bits
*
* @return Status of the command
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CMD_PENDING
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_NULL
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_NOT_ALIGNED
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_SIZE
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BUFFER_FULL
*/
SNVMA_Cmd_Status_t SNVMA_Register (const SNVMA_BufferId_t BufferId,
const uint32_t * p_BufferAddress,
const uint32_t BufferSize);
/**
* @brief Restore a user buffer from a NVM
*
* @details The user buffer information shall first be provided by calling SNVMA_Register
*
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
*
* @param BufferId: Id of the user which ask for buffer registration
*
* @return Status of the command
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_CMD_PENDING
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_REGISTERED
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BANK_EMPTY
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NVM_BANK_CORRUPTED
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFER_CONFIG_MISSMATCH
*/
SNVMA_Cmd_Status_t SNVMA_Restore (const SNVMA_BufferId_t BufferId);
/**
* @brief Register a user buffer to a NVM
*
* @details The user buffer information shall first be provided by calling SNVMA_Register
*
* @details Buffer IDs are hardcoded, please refer to SNVMA_BufferId_t enumeration
*
* @details A buffer write request cannot be scheduled once its NVM is already on a write operation. This will lead
* to a SNVMA_OPERATION_FAILED callback status.
*
* @param BufferId: Id of the user which ask for buffer registration
* @param Callback: Callback function for operation status return - Can be NULL
*
* @return Status of the command
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_OK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOK
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_NOT_INIT
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_KNOWN
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_BUFFERID_NOT_REGISTERED
* @retval SNVMA_Cmd_Status_t::SNVMA_ERROR_FLASH_ERROR
*/
SNVMA_Cmd_Status_t SNVMA_Write (const SNVMA_BufferId_t BufferId,
void (* Callback) (SNVMA_Callback_Status_t));
#ifdef __cplusplus
}
#endif
#endif /*SIMPLE_NVM_ARBITER_H */

View File

@@ -0,0 +1,135 @@
/**
******************************************************************************
* @file simple_nvm_arbiter_common.h
* @author MCD Application Team
* @brief Common header of simple_nvm_arbiter.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef SIMPLE_NVM_ARBITER_COMMON_H
#define SIMPLE_NVM_ARBITER_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
/* Exported constants --------------------------------------------------------*/
/* Maximum number of different NVM Identifiers */
#define SNVMA_MAX_NUMBER_NVM 32u
/* Maximum number of buffer per NVM */
#define SNVMA_MAX_NUMBER_BUFFER 4u
/* Minimum number of bank per NVM */
#define SNVMA_MIN_NUMBER_BANK 2u
/* Exported types ------------------------------------------------------------*/
/* SNVMA command status */
typedef enum SNVMA_Cmd_Status
{
SNVMA_ERROR_OK,
SNVMA_ERROR_NOK,
SNVMA_ERROR_NOT_INIT,
SNVMA_ERROR_ALREADY_INIT,
SNVMA_ERROR_CMD_PENDING,
SNVMA_ERROR_BANK_OP_ONGOING,
SNVMA_ERROR_NVM_NULL,
SNVMA_ERROR_NVM_NOT_ALIGNED,
SNVMA_ERROR_NVM_OVERLAP_FLASH,
SNVMA_ERROR_NVM_BUFFER_FULL,
SNVMA_ERROR_NVM_BANK_EMPTY,
SNVMA_ERROR_NVM_BANK_CORRUPTED,
SNVMA_ERROR_CRC_INIT,
SNVMA_ERROR_BANK_NUMBER,
SNVMA_ERROR_BANK_SIZE,
SNVMA_ERROR_BUFFERID_NOT_KNOWN,
SNVMA_ERROR_BUFFERID_NOT_REGISTERED,
SNVMA_ERROR_BUFFER_NULL,
SNVMA_ERROR_BUFFER_NOT_ALIGNED,
SNVMA_ERROR_BUFFER_SIZE,
SNVMA_ERROR_BUFFER_CONFIG_MISSMATCH,
SNVMA_ERROR_FLASH_ERROR,
SNVMA_ERROR_UNKNOWN,
} SNVMA_Cmd_Status_t;
/* SNVMA callback status */
typedef enum SNVMA_Callback_Status
{
SNVMA_OPERATION_COMPLETE,
SNVMA_OPERATION_FAILED
}SNVMA_Callback_Status_t;
/* Buffer Element */
typedef struct SNVMA_BufferElt
{
/* Buffer address */
uint32_t * p_Addr;
/* Buffer size */
uint32_t Size;
}SNVMA_BufferElt_t;
/* Bank Element */
typedef struct SNVMA_BankElt
{
/* Pointer onto the start address of the bank */
uint32_t * p_StartAddr;
/* Pointer onto the buffer address in the bank */
uint32_t * ap_BufferAddr[SNVMA_MAX_NUMBER_BUFFER];
}SNVMA_BankElt_t;
/* NVM Element */
typedef struct SNVMA_NvmElt
{
/* Bank number */
uint8_t BankNumber;
/* Bank size */
uint8_t BankSize;
/*
* Pending buffer write operations bit mask
*
* ----------------------------------------
* + 4 bits | 4 bits +
* + ------------------------------------ +
* + Active Request | New Request +
* ----------------------------------------
*
*/
uint8_t PendingBufferWriteOp;
/* Pointer onto the bank list */
SNVMA_BankElt_t * p_BankList;
/* Pointer onto the bank being used for write operation */
SNVMA_BankElt_t * p_BankForWrite;
/* Pointer onto the bank being used for restore operation */
SNVMA_BankElt_t * p_BankForRestore;
/* Callback pointer array */
void (* a_Callback [SNVMA_MAX_NUMBER_BUFFER]) (SNVMA_Callback_Status_t);
/* Array of buffers in use */
SNVMA_BufferElt_t a_Buffers [SNVMA_MAX_NUMBER_BUFFER];
}SNVMA_NvmElt_t;
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /*SIMPLE_NVM_ARBITER_COMMON_H */

View File

@@ -0,0 +1,298 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file log_module.c
* @author MCD Application Team
* @brief Source file of the log module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include <stdio.h> /* vsnprintf */
#include "log_module.h"
#include "stm32_adv_trace.h"
#include "utilities_conf.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* Definition of 'End Of Line' */
#define ENDOFLINE_SIZE (0x01u)
#define ENDOFLINE_CHAR '\n'
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Exported constants --------------------------------------------------------*/
/* Global const struct variables to make the life of the user easier */
const Log_Module_t LOG_MODULE_DEFAULT_CONFIGURATION =
{
.verbose_level = LOG_VERBOSE_ERROR,
.region_mask = (LOG_REGION_ALL_REGIONS)
};
const Log_Verbose_Level_t LOG_VERBOSE_DEFAULT = LOG_VERBOSE_ERROR;
const Log_Region_t LOG_REGION_MASK_DEFAULT = LOG_REGION_ALL_REGIONS;
const Log_Color_t LOG_COLOR_DEFAULT_CONFIGURATION[] =
{
LOG_COLOR_CODE_DEFAULT, // For Region BLE
LOG_COLOR_CODE_DEFAULT, // For Region System
LOG_COLOR_CODE_DEFAULT, // For Region APP
LOG_COLOR_CODE_RED, // For Region LinkLayer
LOG_COLOR_CODE_YELLOW, // For Region MAC
LOG_COLOR_CODE_GREEN, // For Region Zigbee
LOG_COLOR_CODE_GREEN, // For Region Thread
LOG_COLOR_CODE_DEFAULT, // For Region RTOS
/* USER CODE BEGIN LOG_COLOR_DEFAULT_CONFIGURATION */
/* USER CODE END LOG_COLOR_DEFAULT_CONFIGURATION */
};
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Private variables ---------------------------------------------------------*/
static uint32_t current_region_mask;
static Log_Verbose_Level_t current_verbose_level;
static Log_Color_t current_color_list[32];
CallBack_TimeStamp * log_timestamp_function;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
static uint32_t Get_Region_Mask(Log_Region_t Region);
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region);
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Functions Definition ------------------------------------------------------*/
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
/**
* @brief Add the color (in function of Region) on the start of Log sentence.
*
* @param TextBuffer Pointer on the log buffer
* @param SizeMax The maximum number of bytes that will be written to the buffer.
* @param Region Region of the log to apply its corresponding color.
*
* @return Length of the new Log.
*/
static uint16_t RegionToColor(char * TextBuffer, uint16_t SizeMax, Log_Region_t Region)
{
uint16_t text_length = 0;
Log_Color_t color;
static Log_Color_t previous_color = LOG_COLOR_NONE;
if (Region != LOG_MODULE_ALL_REGION_MASK)
{
color = current_color_list[Region];
}
else
{
color = LOG_COLOR_CODE_DEFAULT;
}
/* Insert Color code only if previous is not the same */
if (color != previous_color)
{
if (color == LOG_COLOR_CODE_DEFAULT)
{
snprintf(TextBuffer, SizeMax, "\x1b[0m");
}
else
{
snprintf(TextBuffer, SizeMax, "\x1b[0;%02dm", color);
}
previous_color = color;
text_length = strlen(TextBuffer);
}
return text_length;
}
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
void Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, va_list Args)
{
uint16_t tmp_size = 0;
uint16_t buffer_size = 0;
char full_text[UTIL_ADV_TRACE_TMP_BUF_SIZE + 1u];
/* USER CODE BEGIN Log_Module_PrintWithArg_1 */
/* USER CODE END Log_Module_PrintWithArg_1 */
/* If the verbose level of the given log is not enabled, then we do not print the log */
if (VerboseLevel > current_verbose_level)
{
return;
}
/* If the region for the given log is not enabled, then we do not print the log */
if ((Get_Region_Mask(Region) & current_region_mask) == 0u)
{
return;
}
#if (LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0)
/* Add to full_text the color matching the region */
tmp_size = RegionToColor(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Region);
buffer_size += tmp_size;
#endif /* LOG_INSERT_COLOR_INSIDE_THE_TRACE != 0 */
#if (LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0)
if (log_timestamp_function != NULL)
{
tmp_size = UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size;
log_timestamp_function(&full_text[buffer_size], tmp_size, &tmp_size);
buffer_size += tmp_size;
}
#endif /* LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE != 0 */
/* Copy the data */
tmp_size = (uint16_t)vsnprintf(&full_text[buffer_size], (UTIL_ADV_TRACE_TMP_BUF_SIZE - buffer_size), Text, Args);
buffer_size += tmp_size;
/* USER CODE BEGIN Log_Module_PrintWithArg_2 */
/* USER CODE END Log_Module_PrintWithArg_2 */
#if (LOG_INSERT_EOL_INSIDE_THE_TRACE != 0)
/* Add End Of Line if needed */
if (buffer_size > 1)
{
if ((full_text[buffer_size - 1] != ENDOFLINE_CHAR) && (full_text[buffer_size - 2] != ENDOFLINE_CHAR))
{
full_text[buffer_size++] = ENDOFLINE_CHAR;
full_text[buffer_size] = 0;
}
}
#endif /* LOG_INSERT_EOL_INSIDE_THE_TRACE != 0 */
/* USER CODE BEGIN Log_Module_PrintWithArg_3 */
/* USER CODE END Log_Module_PrintWithArg_3 */
/* Send full_text to ADV Traces */
UTIL_ADV_TRACE_Send((const uint8_t *)full_text, buffer_size);
}
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...)
{
#if (CFG_LOG_SUPPORTED != 0)
va_list variadic_args;
va_start(variadic_args, Text);
Log_Module_PrintWithArg(VerboseLevel, Region, Text, variadic_args);
va_end(variadic_args);
#else /* (CFG_LOG_SUPPORTED != 0) */
UNUSED(VerboseLevel);
UNUSED(Region);
UNUSED(Text);
#endif /* (CFG_LOG_SUPPORTED != 0) */
}
void Log_Module_Init(Log_Module_t LogConfiguration)
{
UTIL_ADV_TRACE_Init();
memcpy(&current_color_list, &LOG_COLOR_DEFAULT_CONFIGURATION, sizeof(LOG_COLOR_DEFAULT_CONFIGURATION));
Log_Module_Set_Verbose_Level(LogConfiguration.verbose_level);
Log_Module_Set_Multiple_Regions(LogConfiguration.region_mask);
log_timestamp_function = NULL;
}
void Log_Module_DeInit(void)
{
UTIL_ADV_TRACE_DeInit();
}
void Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel)
{
current_verbose_level = NewVerboseLevel;
}
void Log_Module_Set_Region(Log_Region_t NewRegion)
{
current_region_mask = Get_Region_Mask(NewRegion);
}
void Log_Module_Add_Region(Log_Region_t NewRegion)
{
current_region_mask |= Get_Region_Mask(NewRegion);
}
void Log_Module_Remove_Region(Log_Region_t Region)
{
current_region_mask &= ~Get_Region_Mask(Region);
}
void Log_Module_Enable_All_Regions(void)
{
Log_Module_Set_Region(LOG_REGION_ALL_REGIONS);
}
static uint32_t Get_Region_Mask(Log_Region_t Region)
{
if (Region == LOG_REGION_ALL_REGIONS)
{
/* Return the full mask */
return ((uint32_t)LOG_MODULE_ALL_REGION_MASK);
}
else
{
/* Return the bit matching the region */
return ((uint32_t)(1U << ((uint32_t)Region)));
}
}
void Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask)
{
current_region_mask = NewRegionMask;
}
void Log_Module_Set_Color(Log_Region_t Region, Log_Color_t Color)
{
if ( Region != LOG_MODULE_ALL_REGION_MASK )
{
current_color_list[Region] = Color;
}
}
void Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction)
{
log_timestamp_function = TimeStampFunction;
}
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */

View File

@@ -0,0 +1,220 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file log_module.h
* @author MCD Application Team
* @brief Header file of the log module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LOG_MODULE_H
#define LOG_MODULE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include <stdarg.h>
#include <stdint.h>
#include <stdbool.h>
#include "log_module_conf.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* Log module types */
/**
* @brief Data type to initialize the module by calling Log_Module_Init.
* verbose_level : A value of type Log_Verbose_Level_t.
* region_mask : A mask based on Log_Region_t.
* You can directly assign it to LOG_REGION_ALL_REGIONS,
* or select only some regions :
* (1U << LOG_REGION_BLE | 1U << LOG_REGION_APP)
*/
typedef struct
{
Log_Verbose_Level_t verbose_level;
uint32_t region_mask;
} Log_Module_t;
/**
* @brief Callback function to insert Time Stamp.
*
* @param Data The data into which to insert the TimeStamp.
* @param SizeMax The maximum size for the TimeStamp insert.
* @param TimeStampSize Pointer to update with the size of the TimeStamp inserted into data.
*/
typedef void CallBack_TimeStamp(char * Data, uint16_t SizeMax, uint16_t * TimeStampSize);
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
/* Global const struct variables to make the life of the user easier */
/**
* @brief A const struct with default parameters for the log module.
* Its main use is to pass it as parameter to Log_Module_Init.
*/
extern const Log_Module_t LOG_MODULE_DEFAULT_CONFIGURATION;
/**
* @brief A const enum variable with the verbose level set to LOG_VERBOSE_ERROR.
* The levels include the lower levels in the logs.
*
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
*/
extern const Log_Verbose_Level_t LOG_VERBOSE_DEFAULT;
/**
* @brief A const enum variable to include all regions in the logs.
*/
extern const Log_Region_t LOG_REGION_MASK_DEFAULT;
/* USER CODE BEGIN EC */
/* USER CODE END EC */
/* Exported functions prototypes ---------------------------------------------*/
/* Module API - Module configuration */
/**
* @brief Initialization of the log module.
*
* @param LogConfiguration The configuration of the log module, of type Log_Module_t.
* @return None.
*/
void Log_Module_Init(Log_Module_t LogConfiguration);
/**
* @brief DeInitialization of the log module.
*
* @param None.
* @return None.
*/
void Log_Module_DeInit(void);
/**
* @brief Set the verbose level of the log.
* The levels include the lower levels in the logs.
*
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
*
* @param NewVerboseLevel The new verbose level to be set, of type Log_Verbose_Level_t
* @return None
*/
void Log_Module_Set_Verbose_Level(Log_Verbose_Level_t NewVerboseLevel);
/**
* @brief Replace the current regions in use and only set the given region.
*
* @param NewRegion The new region to use, of type Log_Region_t.
* @return None.
*/
void Log_Module_Set_Region(Log_Region_t NewRegion);
/**
* @brief Replace the current regions in use and set one or several as replacement.
*
* @param NewRegionMask A mask, of type uint32_t, where each bit corresponds to a region.
* You can directly assign it to LOG_REGION_ALL_REGIONS to enable all of them,
* or select only some regions, e.g. (1U << LOG_REGION_BLE | 1U << LOG_REGION_APP)
* @return None.
*/
void Log_Module_Set_Multiple_Regions(uint32_t NewRegionMask);
/**
* @brief Add to the current region mask the given region.
*
* @param NewRegion The new region to use, alongside the others, of type Log_Region_t.
* @return None.
*/
void Log_Module_Add_Region(Log_Region_t NewRegion);
/**
* @brief Remove from the current region mask the given region.
*
* @param Region The region to remove, of type Log_Region_t.
* @return None.
*/
void Log_Module_Remove_Region(Log_Region_t Region);
/**
* @brief Enable all the regions.
*
* @param None.
* @return None.
*/
void Log_Module_Enable_All_Regions(void);
/**
* @brief Set the color for a region.
*
* @param Region The region where apply the color, type Log_Region_t.
* @param Color The color to apply to selected region, of type Log_Color_t.
* @return None.
*/
void Log_Module_Set_Color(Log_Region_t Region, Log_Color_t Color);
/**
* @brief Register a callback function to insert the TimeStamp into the data.
*
* @param TimeStampFunction Callback function to insert TimeStamp.
* This function is typedef void (char * data, uint16_t size_max, uint16_t * timestamp_size);
* Where data is the location where to insert the new TimeStamp, and timestamp_size is the size of this insertion.
* @return None.
*/
void Log_Module_RegisterTimeStampFunction(CallBack_TimeStamp * TimeStampFunction);
/* Module API - Wrapper function */
/**
* @brief Underlying function of all the LOG_xxx macros.
*
* @param VerboseLevel The level of verbose used for this Log, of type Log_Verbose_Level_t.
* @param Region The region set for this log, of type Log_Region_t.
* @param Text The text to be printed.
* @param ... Any other parameters to be printed with the text.
* E.g. an int variable. as 3rd parameter, as long as %d is in text.
*
* @return None.
*/
void Log_Module_Print(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, ...);
/**
* @brief Function of log with already a arg list.
*
* @param VerboseLevel The level of verbose used for this Log, of type Log_Verbose_Level_t.
* @param Region The region set for this log, of type Log_Region_t.
* @param Text The text to be printed
* @param Args Arguments list, of type va_list.
*
* @return None.
*/
void Log_Module_PrintWithArg(Log_Verbose_Level_t VerboseLevel, Log_Region_t Region, const char * Text, va_list Args);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */
#ifdef __cplusplus
}
#endif
#endif /* LOG_MODULE_H */

View File

@@ -0,0 +1,294 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file log_module_conf.h
* @author MCD Application Team
* @brief Header file of the log module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef LOG_MODULE_CONF_H
#define LOG_MODULE_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "app_conf.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Module configuration ------------------------------------------------------*/
/**
* @brief When this define is set to 0, there is no time stamp added to the trace data.
* When this define is set to 1, the time stamp is added to the trace data,
* according to the function registered with Log_Module_RegisterTimeStampFunction.
*/
#define LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE CFG_LOG_INSERT_TIME_STAMP_INSIDE_THE_TRACE
/**
* @brief When this define is set to 0, the color of the trace data remains the same for all regions.
* When this define is set to 1, the color added to the trace data is based on LOG_COLOR_DEFAULT_CONFIGURATION.
*/
#define LOG_INSERT_COLOR_INSIDE_THE_TRACE CFG_LOG_INSERT_COLOR_INSIDE_THE_TRACE
/**
* @brief When this define is set to 0, the trace data is not modified.
* When this define is set to 1, if there is no ENDOFLINE_CHAR as last
* character in the trace data, then one is added.
*/
#define LOG_INSERT_EOL_INSIDE_THE_TRACE CFG_LOG_INSERT_EOL_INSIDE_THE_TRACE
/* USER CODE BEGIN Module configuration */
/* USER CODE END Module configuration */
/* Private defines -----------------------------------------------------------*/
/* These defines are related to the UTIL_ADV_TRACE. Do not modify them please. */
#define LOG_MODULE_MIN_VERBOSE_LEVEL (0)
#define LOG_MODULE_MAX_VERBOSE_LEVEL (0xFFFFFFFF)
#define LOG_MODULE_MIN_REGION_VALUE (0)
#define LOG_MODULE_ALL_REGION_MASK (0xFFFFFFFF)
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Exported types ------------------------------------------------------------*/
/* Log module types */
/**
* @brief Customizable enum describing the verbose levels used by the log module.
* The levels include the lower levels in the logs.
*
* E.g. LOG_VERBOSE_ERROR means LOG_VERBOSE_ERROR logs will be printed,
* as well as LOG_VERBOSE_INFO, but not the others with higher values.
*
* The min and max ranges are defined by LOG_MODULE_MIN_VERBOSE_LEVEL
* and LOG_MODULE_MAX_VERBOSE_LEVEL.
*
* The user can add its own levels but must NOT add a value to the said
* levels. Verbose levels are handled by the UTIL_ADV_TRACE.
*/
typedef enum
{
LOG_VERBOSE_INFO = LOG_MODULE_MIN_VERBOSE_LEVEL,
/* USER CODE BEGIN Log_Verbose_Level_t_0 */
/* USER CODE END Log_Verbose_Level_t_0 */
LOG_VERBOSE_ERROR,
/* USER CODE BEGIN Log_Verbose_Level_t_1 */
/* USER CODE END Log_Verbose_Level_t_1 */
LOG_VERBOSE_WARNING,
/* USER CODE BEGIN Log_Verbose_Level_t_2 */
/* USER CODE END Log_Verbose_Level_t_2 */
LOG_VERBOSE_DEBUG,
/* USER CODE BEGIN Log_Verbose_Level_t_3 */
/* USER CODE END Log_Verbose_Level_t_3 */
LOG_VERBOSE_ALL_LOGS = LOG_MODULE_MAX_VERBOSE_LEVEL,
} Log_Verbose_Level_t;
/**
* @brief Customizable enum describing the regions used by the log module.
* Regions are used to separate the logs into different places.
*
* Let's say you have a Task 1 and a Task 2.
* Both of them have Info and Debug logs.
*
* By using them as such, i.e. with the same regions, you'll
* print the logs of the 2 tasks as long as the verbose is Info or Debug.
*
* If you create a region for Task 1 and another for Task 2, you can
* split the logs between them, and, if needed, only print the Debug
* logs for Task 1 only (i.e. Task 1 logs for Info and Debug).
*
* Behind the scenes is a mask into which each region is a bit.
* The user can add its own regions but must NOT add a value to them.
* The log module handles the mask on its own.
*/
typedef enum
{
LOG_REGION_BLE = LOG_MODULE_MIN_REGION_VALUE,
LOG_REGION_SYSTEM,
LOG_REGION_APP,
LOG_REGION_LINKLAYER,
LOG_REGION_MAC,
LOG_REGION_ZIGBEE,
LOG_REGION_THREAD,
LOG_REGION_RTOS,
/* USER CODE BEGIN Log_Region_t */
/* USER CODE END Log_Region_t */
LOG_REGION_ALL_REGIONS = LOG_MODULE_ALL_REGION_MASK,
} Log_Region_t;
typedef enum
{
LOG_COLOR_NONE = 0, /* Initialization */
LOG_COLOR_CODE_DEFAULT = 37, /* White */
LOG_COLOR_CODE_RED = 91,
LOG_COLOR_CODE_GREEN = 92,
LOG_COLOR_CODE_YELLOW = 93,
LOG_COLOR_CODE_CYAN = 96,
/* USER CODE BEGIN Log_Color_t */
/* USER CODE END Log_Color_t */
} Log_Color_t;
/* USER CODE BEGIN ET */
/* USER CODE END ET */
/* Exported macro ------------------------------------------------------------*/
/* Display 64 bits number for all compiler. */
/* Example : LOG_INFO_APP( "New Device : " LOG_DISPLAY64() " installed in %d seconds", LOG_NUMBER64( dlDevice ), iTime ); */
#define LOG_DISPLAY64() "0x%08X%08X"
#define LOG_NUMBER64( number ) (uint32_t)( number >> 32u ), (uint32_t)( number )
/* Module API - Log macros for each region */
/* LOG_REGION_BLE */
#if (CFG_LOG_SUPPORTED != 0)
#define LOG_INFO_BLE(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_BLE, __VA_ARGS__)
#define LOG_ERROR_BLE(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_BLE, __VA_ARGS__)
#define LOG_WARNING_BLE(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_BLE, __VA_ARGS__)
#define LOG_DEBUG_BLE(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_BLE, __VA_ARGS__)
#else /* (CFG_LOG_SUPPORTED != 0) */
#define LOG_INFO_BLE(...) do {} while(0)
#define LOG_ERROR_BLE(...) do {} while(0)
#define LOG_WARNING_BLE(...) do {} while(0)
#define LOG_DEBUG_BLE(...) do {} while(0)
#endif /* (CFG_LOG_SUPPORTED != 0) */
/* USER CODE BEGIN LOG_REGION_BLE */
/**
* Add inside this user section your defines to match the new verbose levels you
* created into Log_Verbose_Level_t.
* Example :
* #define LOG_CUSTOM_BLE(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_BLE, __VA_ARGS__);
*
* You don't need to update all regions with your custom values.
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
*/
/* USER CODE END LOG_REGION_BLE */
/* LOG_REGION_SYSTEM */
#if (CFG_LOG_SUPPORTED != 0)
#define LOG_INFO_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_SYSTEM, __VA_ARGS__)
#define LOG_ERROR_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_SYSTEM, __VA_ARGS__)
#define LOG_WARNING_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_SYSTEM, __VA_ARGS__)
#define LOG_DEBUG_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_SYSTEM, __VA_ARGS__)
#else /* (CFG_LOG_SUPPORTED != 0) */
#define LOG_INFO_SYSTEM(...) do {} while(0)
#define LOG_ERROR_SYSTEM(...) do {} while(0)
#define LOG_WARNING_SYSTEM(...) do {} while(0)
#define LOG_DEBUG_SYSTEM(...) do {} while(0)
#endif /* (CFG_LOG_SUPPORTED != 0) */
/* USER CODE BEGIN LOG_REGION_SYSTEM */
/**
* Add inside this user section your defines to match the new verbose levels you
* created into Log_Verbose_Level_t.
* Example :
* #define LOG_CUSTOM_SYSTEM(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_SYSTEM, __VA_ARGS__);
*
* You don't need to update all regions with your custom values.
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
*/
/* USER CODE END LOG_REGION_SYSTEM */
/* LOG_REGION_APP */
#if (CFG_LOG_SUPPORTED != 0)
#define LOG_INFO_APP(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_APP, __VA_ARGS__)
#define LOG_ERROR_APP(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_APP, __VA_ARGS__)
#define LOG_WARNING_APP(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_APP, __VA_ARGS__)
#define LOG_DEBUG_APP(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_APP, __VA_ARGS__)
#else /* (CFG_LOG_SUPPORTED != 0) */
#define LOG_INFO_APP(...) do {} while(0)
#define LOG_ERROR_APP(...) do {} while(0)
#define LOG_WARNING_APP(...) do {} while(0)
#define LOG_DEBUG_APP(...) do {} while(0)
#endif /* (CFG_LOG_SUPPORTED != 0) */
/* USER CODE BEGIN LOG_REGION_APP */
/**
* Add inside this user section your defines to match the new verbose levels you
* created into Log_Verbose_Level_t.
* Example :
* #define LOG_CUSTOM_APP(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_APP, __VA_ARGS__);
*
* You don't need to update all regions with your custom values.
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
*/
/* USER CODE END LOG_REGION_APP */
/* LOG_REGION_LINKLAYER */
#if (CFG_LOG_SUPPORTED != 0)
#define LOG_INFO_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_LINKLAYER, __VA_ARGS__)
#define LOG_ERROR_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_LINKLAYER, __VA_ARGS__)
#define LOG_WARNING_LINKLAYER(...)Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_LINKLAYER, __VA_ARGS__)
#define LOG_DEBUG_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_LINKLAYER, __VA_ARGS__)
#else /* (CFG_LOG_SUPPORTED != 0) */
#define LOG_INFO_LINKLAYER(...) do {} while(0)
#define LOG_ERROR_LINKLAYER(...) do {} while(0)
#define LOG_WARNING_LINKLAYER(...)do {} while(0)
#define LOG_DEBUG_LINKLAYER(...) do {} while(0)
#endif /* (CFG_LOG_SUPPORTED != 0) */
/* USER CODE BEGIN LOG_REGION_LINKLAYER */
/**
* Add inside this user section your defines to match the new verbose levels you
* created into Log_Verbose_Level_t.
* Example :
* #define LOG_CUSTOM_LINKLAYER(...) Log_Module_Print( LOG_VERBOSE_CUSTOM, LOG_REGION_LINKLAYER, __VA_ARGS__);
*
* You don't need to update all regions with your custom values.
* Do it accordingly to your needs. E.g you might not need LOG_VERBOSE_CUSTOM for a System region.
*/
/* USER CODE END LOG_REGION_LINKLAYER */
/* USER CODE BEGIN APP_LOG_USER_DEFINES */
/**
* Add inside this user section your defines to match the new regions you
* created into Log_Region_t.
* Example :
#if (CFG_LOG_SUPPORTED != 0)
#define LOG_INFO_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_INFO, LOG_REGION_CUSTOM, __VA_ARGS__)
#define LOG_ERROR_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_ERROR, LOG_REGION_CUSTOM, __VA_ARGS__)
#define LOG_WARNING_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_WARNING, LOG_REGION_CUSTOM, __VA_ARGS__)
#define LOG_DEBUG_CUSTOM(...) Log_Module_Print( LOG_VERBOSE_DEBUG, LOG_REGION_CUSTOM, __VA_ARGS__)
#else
#define LOG_INFO_CUSTOM(...) do {} while(0)
#define LOG_ERROR_CUSTOM(...) do {} while(0)
#define LOG_WARNING_CUSTOM(...) do {} while(0)
#define LOG_DEBUG_CUSTOM(...) do {} while(0)
#endif
*/
/* USER CODE END APP_LOG_USER_DEFINES */
#ifdef __cplusplus
}
#endif
#endif /* LOG_MODULE_CONF_H */

View File

@@ -0,0 +1,716 @@
/**
******************************************************************************
* @file advanced_memory_manager.c
* @author MCD Application Team
* @brief Memory Manager
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm_list.h"
#include "utilities_conf.h"
#include "advanced_memory_manager.h"
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/* Defines that the module is not initialized */
#define NOT_INITIALIZED 0x00u
/* Defines that the module is initialized */
#define INITIALIZED 0x01u
/* Defines the bit to check for 32bits aligned values */
#define MASK_ALIGNED_32BITS 0x03u
/*
Defines the length of the Virtual Memory Header in 32bits
----------------------------------------
| +++ 8bits +++ | +++++++ 24bits +++++++ |
| VirtualMem ID | Buffer Size (n*32bits) |
----------------------------------------
*/
#define VIRTUAL_MEMORY_HEADER_SIZE 0x01
/* Position of the ID field in Virtual Memory Header */
#define VIRTUAL_MEMORY_HEADER_ID_POS 0x18
/* Mask of the ID field in Virtual Memory Header */
#define VIRTUAL_MEMORY_HEADER_ID_MASK 0xFF000000
/* Position of the Buffer Size field in Virtual Memory Header */
#define VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS 0x00
/* Mask of the Buffer Size field in Virtual Memory Header */
#define VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK 0x00FFFFFF
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* AMM Initialized flag */
static uint8_t AmmInitialized = NOT_INITIALIZED;
/* AMM pool address */
static uint32_t * p_AmmPoolAddress;
/* AMM pool size */
static uint32_t AmmPoolSize;
/* AMM occupied shared pool size */
static uint32_t AmmOccupiedSharedPoolSize;
#if (AMM_USE_MEMORY_STATISTICS == 1)
/* AMM peak shared pool size */
static uint32_t AmmPeakSharedPoolSize;
#endif /* AMM_USE_MEMORY_STATISTICS */
/* AMM needed virtual memory */
static uint32_t AmmRequiredVirtualMemorySize;
/* AMM virtual memory number */
static uint32_t AmmVirtualMemoryNumber;
/* List of Virtual Memories info */
static VirtualMemoryInfo_t * p_AmmVirtualMemoryList;
/* Handler of the Basic Memory Manager functions */
static AMM_BasicMemoryManagerFunctions_t AmmBmmFunctionsHandler;
/* Pointer on the first element of the pending callbacks */
static AMM_VirtualMemoryCallbackHeader_t AmmPendingCallback;
/* Pointer on the first element of the active callbacks */
static AMM_VirtualMemoryCallbackHeader_t AmmActiveCallback;
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/**
* @brief Push a callback structure into the Pending FIFO
* @param p_CallbackElt: Pointer onto the callback to push
* @return None
*/
static inline void pushPending (AMM_VirtualMemoryCallbackFunction_t * const p_CallbackElt);
/**
* @brief Push the Pending callback(s) into the Active FIFO
* @return None
*/
static inline void passPendingToActive (void);
/**
* @brief Pop a callback structure from the Active FIFO
* @return Pointer onto the popped callback
*/
static inline AMM_VirtualMemoryCallbackFunction_t * popActive (void);
/* Functions Definition ------------------------------------------------------*/
#if (AMM_USE_MEMORY_STATISTICS == 1)
uint32_t GetCurrentOccupation (const uint8_t VirtualMemoryId)
{
uint32_t currentOccupation = 0x00;
if (AmmInitialized == INITIALIZED)
{
/* Shared memory use case */
if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
{
currentOccupation = AmmOccupiedSharedPoolSize;
}
else
{
/* Check virtual memory info */
for (uint32_t memIdx = 0x00;
(memIdx < AmmVirtualMemoryNumber) && (currentOccupation == 0x00);
memIdx++)
{
/* Check if ID is known */
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
{
currentOccupation = p_AmmVirtualMemoryList[memIdx].OccupiedSize;
}
}
}
}
return currentOccupation;
}
uint32_t GetPeakOccupation (const uint8_t VirtualMemoryId)
{
uint32_t peakOccupation = 0x00;
if (AmmInitialized == INITIALIZED)
{
/* Shared memory use case */
if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
{
peakOccupation = AmmPeakSharedPoolSize;
}
else
{
/* Check virtual memory info */
for (uint32_t memIdx = 0x00;
(memIdx < AmmVirtualMemoryNumber) && (peakOccupation == 0x00);
memIdx++)
{
/* Check if ID is known */
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
{
peakOccupation = p_AmmVirtualMemoryList[memIdx].PeakOccupationSize;
}
}
}
}
return peakOccupation;
}
#endif /* AMM_USE_MEMORY_STATISTICS */
AMM_Function_Error_t AMM_Init (const AMM_InitParameters_t * const p_InitParams)
{
AMM_Function_Error_t error = AMM_ERROR_NOK;
uint32_t neededPoolSize = 0x00;
/* Check if not already initialized */
if (AmmInitialized == INITIALIZED)
{
error = AMM_ERROR_ALREADY_INIT;
}
/* Check parameter null pointer */
else if (p_InitParams == NULL)
{
error = AMM_ERROR_BAD_POINTER;
}
/* Check Pool address null pointer */
else if (p_InitParams->p_PoolAddr == NULL)
{
error = AMM_ERROR_BAD_POOL_CONFIG;
}
/* Check if Pool address is 32bits aligned */
else if ((MASK_ALIGNED_32BITS & (uint32_t)p_InitParams->p_PoolAddr) != 0)
{
error = AMM_ERROR_BAD_POOL_CONFIG;
}
/* Check Pool size shall be non zero */
else if (p_InitParams->PoolSize == 0)
{
error = AMM_ERROR_BAD_POOL_CONFIG;
}
/* Check that Virtual memories can not be declared without a proper configuration list */
else if ((p_InitParams->VirtualMemoryNumber != 0x00) &&
(p_InitParams->p_VirtualMemoryConfigList == NULL))
{
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
}
else
{
neededPoolSize = p_InitParams->VirtualMemoryNumber * AMM_VIRTUAL_INFO_ELEMENT_SIZE;
/* Check the parameters relative to virtual memories */
for (uint32_t memIdx = 0x00;
(memIdx < p_InitParams->VirtualMemoryNumber) && (error == AMM_ERROR_NOK);
memIdx++)
{
/* Add the amount of needed space for this virtual memory */
neededPoolSize = neededPoolSize + p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize;
/* Check the virtual memory ID. Shall not be zero */
if (p_InitParams->p_VirtualMemoryConfigList[memIdx].Id == 0)
{
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
}
/* Check if size is not zero */
else if (p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize == 0)
{
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
}
/* Check if amount of needed memory has overlapped current pool size */
else if (p_InitParams->PoolSize < neededPoolSize)
{
error = AMM_ERROR_BAD_VIRTUAL_CONFIG;
}
else
{
/* Do nothing, all ok yet */
}
}
/* Check if parameters are still ok */
if (error == AMM_ERROR_NOK)
{
/* Init all private variables: Pool relative */
p_AmmPoolAddress = NULL;
AmmPoolSize = 0x00;
AmmOccupiedSharedPoolSize = 0x00;
AmmRequiredVirtualMemorySize = 0x00;
/* Init all private variables: Virtual Memory relative */
AmmVirtualMemoryNumber = 0x00;
p_AmmVirtualMemoryList = NULL;
/* Init all private variables: BMM relative */
AmmBmmFunctionsHandler.Init = NULL;
AmmBmmFunctionsHandler.Allocate = NULL;
AmmBmmFunctionsHandler.Free = NULL;
/* Init all private variables: Callbacks relative */
AmmPendingCallback.next = NULL;
AmmPendingCallback.prev = NULL;
AmmActiveCallback.next = NULL;
AmmActiveCallback.prev = NULL;
/* First get the Basic Memory Manager functions back */
AMM_RegisterBasicMemoryManager (&AmmBmmFunctionsHandler);
if ((AmmBmmFunctionsHandler.Init == NULL)
|| (AmmBmmFunctionsHandler.Allocate == NULL)
|| (AmmBmmFunctionsHandler.Free == NULL))
{
error = AMM_ERROR_BAD_BMM_REGISTRATION;
}
else
{
/* Store the pool info */
p_AmmPoolAddress = p_InitParams->p_PoolAddr;
AmmPoolSize = p_InitParams->PoolSize;
/* First init the Basic Memory Manager */
AmmBmmFunctionsHandler.Init (p_AmmPoolAddress,
AmmPoolSize);
/* Allocate memory for the virtual memories info */
p_AmmVirtualMemoryList = (VirtualMemoryInfo_t *)
(AmmBmmFunctionsHandler. Allocate (AMM_VIRTUAL_INFO_ELEMENT_SIZE
* p_InitParams->VirtualMemoryNumber));
/* Check if allocation is OK*/
if ((p_AmmVirtualMemoryList == NULL) && (p_InitParams->VirtualMemoryNumber > 0))
{
error = AMM_ERROR_BAD_BMM_ALLOCATION;
}
else
{
/* Init Critical section */
UTIL_SEQ_INIT_CRITICAL_SECTION ();
/* Init both pending and active list */
LST_init_head (&AmmPendingCallback);
LST_init_head (&AmmActiveCallback);
/* Keep going on init, fulfill the virtual memories info */
AmmVirtualMemoryNumber = p_InitParams->VirtualMemoryNumber;
/* Actualize actual shared pool occupied size */
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize + (AMM_VIRTUAL_INFO_ELEMENT_SIZE
* AmmVirtualMemoryNumber);
#if (AMM_USE_MEMORY_STATISTICS == 1)
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
#endif /* AMM_USE_MEMORY_STATISTICS */
for (uint32_t memIdx = 0x00;
memIdx < AmmVirtualMemoryNumber;
memIdx++)
{
p_AmmVirtualMemoryList[memIdx].Id = p_InitParams->p_VirtualMemoryConfigList[memIdx].Id;
p_AmmVirtualMemoryList[memIdx].RequiredSize = p_InitParams->p_VirtualMemoryConfigList[memIdx].BufferSize;
p_AmmVirtualMemoryList[memIdx].OccupiedSize = 0x00;
#if (AMM_USE_MEMORY_STATISTICS == 1)
p_AmmVirtualMemoryList[memIdx].PeakOccupationSize = 0x00;
#endif /* AMM_USE_MEMORY_STATISTICS */
AmmRequiredVirtualMemorySize = AmmRequiredVirtualMemorySize + p_AmmVirtualMemoryList[memIdx].RequiredSize;
}
/* Set init flag */
AmmInitialized = INITIALIZED;
/* All info are stored and AMM is initialized */
error = AMM_ERROR_OK;
}
}
}
}
return error;
}
AMM_Function_Error_t AMM_DeInit (void)
{
AMM_Function_Error_t error = AMM_ERROR_NOK;
/* Check if initialized */
if (AmmInitialized == INITIALIZED)
{
/* Free resources */
AmmBmmFunctionsHandler.Free ((uint32_t *)p_AmmVirtualMemoryList);
/* Reset all the variables */
AmmBmmFunctionsHandler.Init = NULL;
AmmBmmFunctionsHandler.Allocate = NULL;
AmmBmmFunctionsHandler.Free = NULL;
p_AmmPoolAddress = 0x00;
AmmPoolSize = 0x00;
AmmOccupiedSharedPoolSize = 0x00;
AmmRequiredVirtualMemorySize = 0x00;
AmmVirtualMemoryNumber = 0x00;
/* Unset the flag */
AmmInitialized = 0x00;
error = AMM_ERROR_OK;
}
else
{
error = AMM_ERROR_NOT_INIT;
}
return error;
}
AMM_Function_Error_t AMM_Alloc (const uint8_t VirtualMemoryId,
const uint32_t BufferSize,
uint32_t ** pp_AllocBuffer,
AMM_VirtualMemoryCallbackFunction_t * const p_CallBackFunction)
{
AMM_Function_Error_t error = AMM_ERROR_NOK;
uint32_t selfAvailable = 0x00;
uint32_t * p_TmpAllocAddr = NULL;
/* Set pointer to NULL */
*pp_AllocBuffer = NULL;
if (AmmInitialized == NOT_INITIALIZED)
{
error = AMM_ERROR_NOT_INIT;
}
/* Check if buffer size is not zero */
else if (BufferSize == 0)
{
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
}
/* Check if no virtual ID requested */
else if (VirtualMemoryId == AMM_NO_VIRTUAL_ID)
{
/* Enter critical section */
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
/* Check for enough space in the shared pool */
if (BufferSize < (AmmPoolSize - AmmOccupiedSharedPoolSize - AmmRequiredVirtualMemorySize))
{
/* Try Allocation. Do not forget the header */
p_TmpAllocAddr = AmmBmmFunctionsHandler.Allocate (BufferSize + VIRTUAL_MEMORY_HEADER_SIZE);
/* Check if allocation is OK */
if (p_TmpAllocAddr != NULL)
{
/* Fulfill the header */
*p_TmpAllocAddr = (uint32_t)(((uint32_t)VirtualMemoryId << VIRTUAL_MEMORY_HEADER_ID_POS)
& VIRTUAL_MEMORY_HEADER_ID_MASK)
| ((BufferSize << VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS)
& VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK);
/* Provide the right address to user, ie without the header */
*pp_AllocBuffer = (uint32_t *)(p_TmpAllocAddr + VIRTUAL_MEMORY_HEADER_SIZE);
/* Actualize the current memory occupation of the shared space */
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize + BufferSize + VIRTUAL_MEMORY_HEADER_SIZE;
#if (AMM_USE_MEMORY_STATISTICS == 1)
/* Check if peak occupation has to be updated */
if (AmmOccupiedSharedPoolSize > AmmPeakSharedPoolSize)
{
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
}
#endif /* AMM_USE_MEMORY_STATISTICS */
error = AMM_ERROR_OK;
}
else
{
/* Register the callback for a future retry */
pushPending (p_CallBackFunction);
error = AMM_ERROR_ALLOCATION_FAILED;
}
}
else
{
/* Register the callback for a future retry */
pushPending (p_CallBackFunction);
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
}
/* Exit critical section */
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
}
/* A specific ID is requested */
else
{
error = AMM_ERROR_UNKNOWN_ID;
/* Enter critical section */
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
/* Check virtual memory info */
for (uint32_t memIdx = 0x00;
(memIdx < AmmVirtualMemoryNumber) && (error == AMM_ERROR_UNKNOWN_ID);
memIdx++)
{
/* Check if ID is known */
if (VirtualMemoryId == p_AmmVirtualMemoryList[memIdx].Id)
{
/* Check if all the reserved memory has been consumed */
if (p_AmmVirtualMemoryList[memIdx].OccupiedSize < p_AmmVirtualMemoryList[memIdx].RequiredSize)
{
/* Compute what is remaining */
selfAvailable = p_AmmVirtualMemoryList[memIdx].RequiredSize
- p_AmmVirtualMemoryList[memIdx].OccupiedSize;
}
/* Check if there is enough space in the shared pool plus in our virtual memory pool */
if (BufferSize < (AmmPoolSize - AmmOccupiedSharedPoolSize - AmmRequiredVirtualMemorySize + selfAvailable))
{
/* Try Allocation. Do not forget the header */
p_TmpAllocAddr = AmmBmmFunctionsHandler.Allocate ((BufferSize + VIRTUAL_MEMORY_HEADER_SIZE));
/* Check if allocation is OK */
if (p_TmpAllocAddr != NULL)
{
/* Fulfill the header */
*p_TmpAllocAddr = (uint32_t)(((uint32_t)VirtualMemoryId << VIRTUAL_MEMORY_HEADER_ID_POS)
& VIRTUAL_MEMORY_HEADER_ID_MASK)
| ((BufferSize << VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS)
& VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK);
/* Provide the right address to user, ie without the header */
*pp_AllocBuffer = (uint32_t *)(p_TmpAllocAddr + VIRTUAL_MEMORY_HEADER_SIZE);
/* Actualize our current memory occupation */
p_AmmVirtualMemoryList[memIdx].OccupiedSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize
+ BufferSize
+ VIRTUAL_MEMORY_HEADER_SIZE;
#if (AMM_USE_MEMORY_STATISTICS == 1)
/* Check if peak occupation has to be updated */
if (p_AmmVirtualMemoryList[memIdx].OccupiedSize > p_AmmVirtualMemoryList[memIdx].PeakOccupationSize)
{
p_AmmVirtualMemoryList[memIdx].PeakOccupationSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize;
}
#endif /* AMM_USE_MEMORY_STATISTICS */
/* Check for overlapping the reserved memory */
if (p_AmmVirtualMemoryList[memIdx].RequiredSize < p_AmmVirtualMemoryList[memIdx].OccupiedSize)
{
/* Actualize the shared memory occupation */
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize
+ BufferSize - selfAvailable
+ VIRTUAL_MEMORY_HEADER_SIZE;
#if (AMM_USE_MEMORY_STATISTICS == 1)
/* Check if peak occupation has to be updated */
if (AmmOccupiedSharedPoolSize > AmmPeakSharedPoolSize)
{
AmmPeakSharedPoolSize = AmmOccupiedSharedPoolSize;
}
#endif /* AMM_USE_MEMORY_STATISTICS */
}
error = AMM_ERROR_OK;
}
else
{
/* Register the callback for a future retry */
pushPending (p_CallBackFunction);
error = AMM_ERROR_ALLOCATION_FAILED;
}
}
else
{
/* Register the callback for a future retry */
pushPending (p_CallBackFunction);
error = AMM_ERROR_BAD_ALLOCATION_SIZE;
}
}
}
/* Exit critical section */
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
}
return error;
}
AMM_Function_Error_t AMM_Free (uint32_t * const p_BufferAddr)
{
AMM_Function_Error_t error = AMM_ERROR_NOK;
uint8_t virtualId = 0x00;
int32_t occupiedOverRequired = 0x00;
uint32_t allocatedSize = 0x00;
uint32_t * p_TmpAllocAddr = NULL;
if (AmmInitialized == NOT_INITIALIZED)
{
error = AMM_ERROR_NOT_INIT;
}
else if (p_BufferAddr == NULL)
{
error = AMM_ERROR_BAD_POINTER;
}
else if ((MASK_ALIGNED_32BITS & (uint32_t)p_BufferAddr) != 0)
{
error = AMM_ERROR_NOT_ALIGNED;
}
/* Check if address is managed by this AMM */
else if ((p_BufferAddr > (p_AmmPoolAddress + AmmPoolSize))
|| (p_BufferAddr < p_AmmPoolAddress))
{
error = AMM_ERROR_OUT_OF_RANGE;
}
else
{
/* Enter critical section */
UTIL_SEQ_ENTER_CRITICAL_SECTION ();
/* First correct the address by adding the header */
p_TmpAllocAddr = (uint32_t *)(p_BufferAddr - VIRTUAL_MEMORY_HEADER_SIZE);
/* Get the virtual memory information */
virtualId = (*p_TmpAllocAddr & VIRTUAL_MEMORY_HEADER_ID_MASK) >> VIRTUAL_MEMORY_HEADER_ID_POS;
allocatedSize = (*p_TmpAllocAddr & VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_MASK) >> VIRTUAL_MEMORY_HEADER_BUFFER_SIZE_POS;
/* Add header size to allocated size */
allocatedSize = allocatedSize + VIRTUAL_MEMORY_HEADER_SIZE;
/* Free the allocated memory */
AmmBmmFunctionsHandler.Free(p_TmpAllocAddr);
/* Update the occupation counters depending on the ID */
if (virtualId == AMM_NO_VIRTUAL_ID)
{
/* Update the occupation size */
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize - allocatedSize;
error = AMM_ERROR_OK;
}
else
{
error = AMM_ERROR_UNKNOWN_ID;
for (uint32_t memIdx = 0x00;
(memIdx < AmmVirtualMemoryNumber) && (error == AMM_ERROR_UNKNOWN_ID);
memIdx++)
{
/* Check if it is the right ID */
if (virtualId == p_AmmVirtualMemoryList[memIdx].Id)
{
occupiedOverRequired = (p_AmmVirtualMemoryList[memIdx].OccupiedSize - p_AmmVirtualMemoryList[memIdx].RequiredSize);
/* Check whether the occupied size has overlaped the required or not */
if (occupiedOverRequired > 0x00)
{
/* Check if reserved memory is overlapped */
if (allocatedSize > occupiedOverRequired)
{
/* Update the occupation size */
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize
- (p_AmmVirtualMemoryList[memIdx].OccupiedSize
- p_AmmVirtualMemoryList[memIdx].RequiredSize);
}
else
{
AmmOccupiedSharedPoolSize = AmmOccupiedSharedPoolSize - allocatedSize;
}
}
/* Update the occupation size */
p_AmmVirtualMemoryList[memIdx].OccupiedSize = p_AmmVirtualMemoryList[memIdx].OccupiedSize
- allocatedSize;
error = AMM_ERROR_OK;
}
}
}
/* Pop pending callbacks and add them to the active fifo */
passPendingToActive ();
/* Exit critical section */
UTIL_SEQ_EXIT_CRITICAL_SECTION ();
/* Ask the user task to proceed to a background process call */
AMM_ProcessRequest();
}
return error;
}
void AMM_BackgroundProcess (void)
{
AMM_VirtualMemoryCallbackFunction_t * p_tmpCallback = NULL;
do
{
/* Pop an active callback request */
p_tmpCallback = popActive();
if (p_tmpCallback != NULL)
{
/* Invoke the callback for an alloc retry */
p_tmpCallback->Callback();
}
}while (p_tmpCallback != NULL);
}
/* Private Functions Definition ------------------------------------------------------*/
void pushPending (AMM_VirtualMemoryCallbackFunction_t * const p_CallbackElt)
{
if (p_CallbackElt != NULL)
{
/* Add the new callback */
LST_insert_tail (&AmmPendingCallback, (tListNode *)p_CallbackElt);
}
}
void passPendingToActive (void)
{
AMM_VirtualMemoryCallbackFunction_t * p_TmpElt = NULL;
while (LST_is_empty (&AmmPendingCallback) == FALSE)
{
/* Remove the head element */
LST_remove_head (&AmmPendingCallback, (tListNode**)&p_TmpElt);
/* Add at the bottom */
LST_insert_tail (&AmmActiveCallback, (tListNode *)p_TmpElt);
}
}
AMM_VirtualMemoryCallbackFunction_t * popActive (void)
{
AMM_VirtualMemoryCallbackFunction_t * p_error = NULL;
if (LST_is_empty (&AmmActiveCallback) == FALSE)
{
/* Remove last element */
LST_remove_head (&AmmActiveCallback, (tListNode**)&p_error);
}
return p_error;
}

View File

@@ -0,0 +1,281 @@
/**
******************************************************************************
* @file advance_memory_manager.h
* @author MCD Application Team
* @brief Header for advance_memory_manager.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef ADVANCED_MEMORY_MANAGER_H
#define ADVANCED_MEMORY_MANAGER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm_list.h"
/* Exported defines -----------------------------------------------------------*/
/**
* @brief Define for No Virtual Memory ID
*
* @details This ID can be used to allocate memory from the shared pool
*/
#define AMM_NO_VIRTUAL_ID 0x00u
/**
* @brief Size of a virtual memory information element in 32bits
*
* @details At initialization, the Advance Memory Manager allocate as many VM info element as there
* is Virtual Memory to manage.
* Thus user shall provide at the initialization more space for the pool.
*
* ie:
* - sizeOfDesiredPool = 8092
* - numberOfVirtualMemory = 3
* - actualSizeOfThePoolToGive = sizeOfDesiredPool + numberOfVirtualMemory * AMM_VIRTUAL_INFO_ELEMENT_SIZE
*/
#define AMM_VIRTUAL_INFO_ELEMENT_SIZE (uint32_t)(sizeof (VirtualMemoryInfo_t) / sizeof (uint32_t))
/* Exported types ------------------------------------------------------------*/
/* Redefine the header for chained list */
typedef tListNode AMM_VirtualMemoryCallbackHeader_t;
/* Function error enumeration */
typedef enum AMM_Function_Error
{
/* No error code */
AMM_ERROR_OK,
/* Error that occurred before any check */
AMM_ERROR_NOK,
/*Bad pointer error */
AMM_ERROR_BAD_POINTER,
/* Bad pool configuration error */
AMM_ERROR_BAD_POOL_CONFIG,
/* Bad virtual memory configuration error */
AMM_ERROR_BAD_VIRTUAL_CONFIG,
/* Bad BMM registration error */
AMM_ERROR_BAD_BMM_REGISTRATION,
/* Bad BMM allocation error */
AMM_ERROR_BAD_BMM_ALLOCATION,
/* Not aligned address error */
AMM_ERROR_NOT_ALIGNED,
/* Out of range error */
AMM_ERROR_OUT_OF_RANGE,
/* Unknown virtual memory manager ID error */
AMM_ERROR_UNKNOWN_ID,
/* Bad allocation size error */
AMM_ERROR_BAD_ALLOCATION_SIZE,
/* Allocation failed error */
AMM_ERROR_ALLOCATION_FAILED,
/* Already initialized AMM error */
AMM_ERROR_ALREADY_INIT,
/* Not initialized AMM error */
AMM_ERROR_NOT_INIT
} AMM_Function_Error_t;
/**
* @brief Virtual Memory information struct
*/
typedef struct __attribute__((packed, aligned(4))) VirtualMemoryInfo
{
/* Identifier of the Virtual Memory */
uint8_t Id;
/* Size required for this Virtual Memory buffer with a multiple of 32bits */
uint32_t RequiredSize;
/* Current occupation of the Virtual Memory buffer with a multiple of 32bits */
uint32_t OccupiedSize;
#if (AMM_USE_MEMORY_STATISTICS == 1)
/* Peak occupation of the Virtual Memory buffer with a multiple of 32bits */
uint32_t PeakOccupationSize;
#endif /* AMM_USE_MEMORY_STATISTICS */
}VirtualMemoryInfo_t;
/**
* @brief Virtual Memory configuration struct
*/
typedef struct AMM_VirtualMemoryConfig
{
/* ID of the Virtual Memory */
uint8_t Id;
/* Size of the Virtual Memory buffer with a multiple of 32bits.
ie: BufferSize = 4; TotalSize = BufferSize * 32bits
= 4 * 32bits
= 128 bits */
uint32_t BufferSize;
}AMM_VirtualMemoryConfig_t;
/**
* @brief Basic Memory Manager functions struct
*
* @details Structure that handles all the required functions of the Basic Memory Manager.
*/
typedef struct AMM_BasicMemoryManagerFunctions
{
/* Basic Memory Manager Init function - Shall be in bytes - */
void (* Init) (uint32_t * const p_PoolAddr, const uint32_t PoolSize);
/* Basic Memory Manager Allocate function - Shall be in bytes - */
uint32_t * (* Allocate) (const uint32_t BufferSize);
/* Basic Memory Manager Free function */
void (* Free) (uint32_t * const p_BufferAddr);
}AMM_BasicMemoryManagerFunctions_t;
/**
* @brief Advance Memory Manager init struct
*
* @details Structure that contains all the needed parameters to initialize the
* Advance Memory Manager.
*/
typedef struct AMM_InitParameters
{
/* Address of the pool of memory to manage */
uint32_t * p_PoolAddr;
/* Size of the pool with a multiple of 32bits.
ie: PoolSize = 4; TotalSize = PoolSize * 32bits
= 4 * 32bits
= 128 bits */
uint32_t PoolSize;
/* Number of Virtual Memory to create */
uint32_t VirtualMemoryNumber;
/* List of the Virtual Memory configurations */
AMM_VirtualMemoryConfig_t * p_VirtualMemoryConfigList;
}AMM_InitParameters_t;
/**
* @brief Virtual Memory Callback function struct
*/
typedef struct AMM_VirtualMemoryCallbackFunction
{
/* Next and previous callbacks in the list */
AMM_VirtualMemoryCallbackHeader_t Header;
/* Callback function pointer to invoke once memory has been freed */
void (* Callback) (void);
}AMM_VirtualMemoryCallbackFunction_t;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
#if (AMM_USE_MEMORY_STATISTICS == 1)
/**
* @brief Get the Current Occupation of the required virtual memory
* @details @ref AMM_NO_VIRTUAL_ID can be used to get the shared pool occupation
* @param VirtualMemoryId: ID of the Virtual Memory
* @return Value of the current occupation in 32bits words
*/
uint32_t GetCurrentOccupation (const uint8_t VirtualMemoryId);
/**
* @brief Get the Peak Occupation of the required virtual memory
* @details @ref AMM_NO_VIRTUAL_ID can be used to get the shared pool peak occupation
* @param VirtualMemoryId: ID of the Virtual Memory
* @return Value of the peak occupation in 32bits words
*/
uint32_t GetPeakOccupation (const uint8_t VirtualMemoryId);
#endif /* AMM_USE_MEMORY_STATISTICS */
/**
* @brief Initialize the Advance Memory Manager Pool
* @param p_InitParams: Struct of init parameters
* @return Status of the initialization
* @retval AMM_Function_Error_t::AMM_ERROR_OK
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
* @retval AMM_Function_Error_t::AMM_ERROR_ALREADY_INIT
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POOL_CONFIG
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_VIRTUAL_CONFIG
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_BMM_REGISTRATION
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_BMM_ALLOCATION
*/
AMM_Function_Error_t AMM_Init (const AMM_InitParameters_t * const p_InitParams);
/**
* @brief DeInitialize the Advance Memory Manager Pool
* @details This function shall be called once every allocated memory has been freed
* @return Status of the initialization
* @retval AMM_Function_Error_t::AMM_ERROR_OK
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
*/
AMM_Function_Error_t AMM_DeInit (void);
/**
* @brief Allocate a buffer from the Advance Memory Manager Pool
* @param VirtualMemoryId: Virtual Memory Identifier - AMM_NO_VIRTUAL_ID Can be used -
* @param BufferSize: Size of the pool with a multiple of 32bits.
ie: BufferSize = 4; TotalSize = BufferSize * 32bits
= 4 * 32bits
= 128 bits
* @param p_CallBackFunction: Pointer onto the Callback to call in case of failure - Can be NULL -
* @param pp_AllocBuffer: Pointer onto the allocated buffer
* @return Status of the allocation
* @retval AMM_Function_Error_t::AMM_ERROR_OK
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
* @retval AMM_Function_Error_t::AMM_ERROR_UNKNOWN_ID
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_ALLOCATION_SIZE
* @retval AMM_Function_Error_t::AMM_ERROR_ALLOCATION_FAILED
*/
AMM_Function_Error_t AMM_Alloc (const uint8_t VirtualMemoryId,
const uint32_t BufferSize,
uint32_t ** pp_AllocBuffer,
AMM_VirtualMemoryCallbackFunction_t * const p_CallBackFunction);
/**
* @brief Free the allocated buffer from the Advance Memory Manager Pool
* @param p_BufferAddr: Address of the buffer to free
* @return Status of the free
* @retval AMM_Function_Error_t::AMM_ERROR_OK
* @retval AMM_Function_Error_t::AMM_ERROR_NOK
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_INIT
* @retval AMM_Function_Error_t::AMM_ERROR_BAD_POINTER
* @retval AMM_Function_Error_t::AMM_ERROR_NOT_ALIGNED
* @retval AMM_Function_Error_t::AMM_ERROR_OUT_OF_RANGE
* @retval AMM_Function_Error_t::AMM_ERROR_UNKNOWN_ID
*/
AMM_Function_Error_t AMM_Free (uint32_t * const p_BufferAddr);
/**
* @brief Background routine
* @details Background routine that aims to call registered callbacks for an allocation retry
* @return None
*/
void AMM_BackgroundProcess (void);
/* Exported functions to be implemented by the user if required ------------- */
/**
* @brief Register the Basic Memory Manager functions to use
* @param p_BasicMemoryManagerFunctions: Address of the basic memory manager functions
* @return None
*/
void AMM_RegisterBasicMemoryManager (AMM_BasicMemoryManagerFunctions_t * const p_BasicMemoryManagerFunctions);
/**
* @brief Request to application for a Background process run
* @return None
*/
void AMM_ProcessRequest (void);
#ifdef __cplusplus
}
#endif
#endif /* ADVANCED_MEMORY_MANAGER_H */

View File

@@ -0,0 +1,288 @@
/**
******************************************************************************
* @file memory_manager.c
* @author MCD Application Team
* @brief Memory Manager
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
#include "memory_manager.h"
#include "stm_list.h"
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
/**
* The average timing is @32Mhz :
* Legacy MM
* + Alloc = 3.5us
* + Free = 2.5us
* New MM
* + Alloc = 6.5us
* + Free = 4.5us
*/
#define USE_NEW_MM 1
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#if(USE_NEW_MM == 0)
#pragma default_variable_attributes = @"MM_CONTEXT"
static uint8_t QueueSize;
static tListNode BufferPool;
static MM_pCb_t BufferFreeCb;
static uint8_t *p_StartPoolAdd;
static uint8_t *p_EndPoolAdd;
#pragma default_variable_attributes =
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
/**
* @brief Initialize the Pools
* @param p_pool: The pool of memory to manage
* @param pool_size: The size of the pool
* @param elt_size: The size of one element in the pool
* @retval None
*/
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size)
{
uint32_t elt_size_corrected;
QueueSize = 0;
elt_size_corrected = 4*DIVC( elt_size, 4 );
/**
* Save the first and last address of the pool of memory
*/
p_StartPoolAdd = p_pool;
p_EndPoolAdd = p_pool + pool_size - 1;
/**
* Initialize list
*/
LST_init_head (&BufferPool);
/**
* Initialize the queue
*/
while(pool_size >= elt_size_corrected)
{
LST_insert_tail(&BufferPool, (tListNode *)p_pool);
p_pool += elt_size_corrected;
QueueSize++;
pool_size -= elt_size_corrected;
}
return;
}
/**
* @brief Provide a buffer
* @note The buffer allocated to the user shall be at least sizeof(tListNode) bytes
* to store the memory manager chaining information
*
* @param size: The size of the buffer requested
* @param cb: The callback to be called when a buffer is made available later on
* if there is no buffer currently available when this API is called
* @retval The buffer address when available or NULL when there is no buffer
*/
MM_pBufAdd_t MM_GetBuffer( uint32_t size, MM_pCb_t cb )
{
MM_pBufAdd_t buffer_address;
uint32_t primask_bit;
uint8_t allocation_exit = FALSE;
while( allocation_exit == FALSE )
{
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
if ( QueueSize )
{
QueueSize--;
LST_remove_head( &BufferPool, ( tListNode ** )&buffer_address );
if((buffer_address >= p_StartPoolAdd) && (buffer_address <= (p_EndPoolAdd - size + 1)))
{
/* The buffer is in a valid range */
BufferFreeCb = 0;
allocation_exit = TRUE;
}
else
{
/**
* The buffer is not in a valid range.
* Keep the reference out of the memory pool and try again
*/
}
}
else
{
BufferFreeCb = cb;
buffer_address = 0;
allocation_exit = TRUE;
}
__set_PRIMASK( primask_bit ); /**< Restore PRIMASK bit*/
}
return buffer_address;
}
/**
* @brief Release a buffer
* @param p_buffer: The data buffer address
* @retval None
*/
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer )
{
uint32_t primask_bit;
if((p_buffer >= p_StartPoolAdd) && (p_buffer <= p_EndPoolAdd))
{
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
LST_insert_tail( &BufferPool, ( tListNode * )p_buffer );
QueueSize++;
__set_PRIMASK( primask_bit ); /**< Restore PRIMASK bit*/
if( BufferFreeCb )
{
/**
* The application is waiting for a free buffer
*/
BufferFreeCb();
}
}
return;
}
#else
#include "stm32_mm.h"
static uint8_t *p_StartPoolAdd __attribute__((section("MM_CONTEXT")));
static uint8_t *p_EndPoolAdd __attribute__((section("MM_CONTEXT")));
static MM_pCb_t BufferFreeCb __attribute__((section("MM_CONTEXT")));
/* Functions Definition ------------------------------------------------------*/
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size)
{
/**
* Save the first and last address of the pool of memory
*/
p_StartPoolAdd = p_pool;
p_EndPoolAdd = p_pool + pool_size - 1;
UTIL_MM_Init(p_pool, pool_size);
return;
}
/**
* @brief Provide a buffer
* @note The buffer allocated to the user shall be at least sizeof(tListNode) bytes
* to store the memory manager chaining information
* During execution, this API shall not be interrupted with a call to either
* MM_GetBuffer() or MM_ReleaseBuffer()
* MM_GetBuffer() is called only from background so this will never happen
* MM_ReleaseBuffer() is called from IPCC interrupt. Masking IPCC interrupt is
* enough to comply to the requirement
* Note that the primask bit cannot be used as the length of the critical section is too long compare to
* the maximum latency of the BLE Irq. Therefore, the BLE Irq shall not be masked.
*
* @param size: The size of the buffer requested
* @param cb: The callback to be called when a buffer is made available later on
* if there is no buffer currently available when this API is called
* @retval The buffer address when available or NULL when there is no buffer
*/
MM_pBufAdd_t MM_GetBuffer( uint32_t size, MM_pCb_t cb )
{
MM_pBufAdd_t buffer_address;
/* uint32_t nvic_ipcc_status; */
uint8_t allocation_exit = FALSE;
while( allocation_exit == FALSE )
{
/* nvic_ipcc_status = NVIC_GetEnableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn); */ /**< backup IPCC just in case it has been disabled by the user */
/* NVIC_DisableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn); */
__disable_irq();
buffer_address = (MM_pBufAdd_t)UTIL_MM_GetBuffer( size );
__enable_irq();
/*
if(nvic_ipcc_status != 0)
{
NVIC_EnableIRQ(IPCC_C2_RX_C2_TX_HSEM_IRQn);
}
*/
if(buffer_address != 0)
{
if((buffer_address >= p_StartPoolAdd) && (buffer_address <= (p_EndPoolAdd - size + 1)))
{
/* The buffer is in a valid range */
BufferFreeCb = 0;
allocation_exit = TRUE;
}
else
{
/**
* The buffer is not in a valid range.
* Keep the reference out of the memory pool and try again
*/
}
}
else
{
BufferFreeCb = cb;
allocation_exit = TRUE;
}
}
return buffer_address;
}
/**
* @brief Release a buffer
* During execution, this API shall not be interrupted with a call to either
* MM_GetBuffer() or MM_ReleaseBuffer()
* MM_GetBuffer() is called only from background so this will never happen
* MM_ReleaseBuffer() is called from IPCC interrupt so it cannot be nested.
* There is no need of a critical section
* Note that anyway, the primask bit cannot be used as the length of the critical section
* is too long compare to the maximum latency of the BLE Irq. Therefore, the BLE Irq shall not be masked.
*
* @param p_buffer: The data buffer address
* @retval None
*/
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer )
{
if((p_buffer >= p_StartPoolAdd) && (p_buffer <= p_EndPoolAdd))
{
UTIL_MM_ReleaseBuffer( p_buffer );
if( BufferFreeCb )
{
/**
* The application is waiting for a free buffer
*/
BufferFreeCb();
}
}
return;
}
#endif

View File

@@ -0,0 +1,49 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file memory_manager.h
* @author MCD Application Team
* @brief Header for memory_manager.c module
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported defines -----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
typedef void (*MM_pCb_t)( void );
typedef uint8_t (*MM_pBufAdd_t);
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void MM_Init(uint8_t *p_pool, uint32_t pool_size, uint32_t elt_size);
MM_pBufAdd_t MM_GetBuffer(uint32_t size, MM_pCb_t cb );
void MM_ReleaseBuffer( MM_pBufAdd_t p_buffer );
/* Exported functions to be implemented by the user if required ------------- */
#ifdef __cplusplus
}
#endif
#endif /* MEMORY_MANAGER_H */

View File

@@ -0,0 +1,576 @@
/*
* FreeRTOS Kernel V10.4.1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/**
******************************************************************************
* @file stm32_mm.c
* @author MCD Application Team
* @brief Memory Manager Utility
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/*
* A sample implementation of pvPortMalloc() and vPortFree() that combines
* (coalescences) adjacent memory blocks as they are freed, and in so doing
* limits memory fragmentation.
*
* See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the
* memory management pages of https://www.FreeRTOS.org for more information.
*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
#include <stdlib.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
* all the API functions to use the MPU wrappers. That should only be done when
* task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#include "FreeRTOS.h"
#include "task.h"
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 )
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
#endif
#else
#include "utilities_common.h"
#include "stm32_mm.h"
#undef PRIVILEGED_DATA
#define PRIVILEGED_DATA
#undef PRIVILEGED_FUNCTION
#define PRIVILEGED_FUNCTION
#undef portBYTE_ALIGNMENT
#define portBYTE_ALIGNMENT (8)
#undef portBYTE_ALIGNMENT_MASK
#if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif
#if portBYTE_ALIGNMENT == 4
#define portBYTE_ALIGNMENT_MASK ( 0x0003 )
#endif
/* No test marker by default. */
#undef mtCOVERAGE_TEST_MARKER
#define mtCOVERAGE_TEST_MARKER()
#undef configASSERT
#define configASSERT( x )
/* No tracing by default. */
#undef traceMALLOC
#define traceMALLOC( pvReturn, xWantedSize )
#undef traceFREE
#define traceFREE( pvAddress, uiSize )
#undef vTaskSuspendAll
#define vTaskSuspendAll()
#undef xTaskResumeAll
#define xTaskResumeAll() (0)
#endif
/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
/* Assumes 8bit bytes! */
#define heapBITS_PER_BYTE ( ( size_t ) 8 )
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
/* Allocate the memory for the heap. */
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
/* The application writer has already defined the array used for the RTOS
* heap - probably so it can be placed in a special segment or address. */
extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */
#endif
/* Define the linked list structure. This is used to link free blocks in order
* of their memory address. */
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
size_t xBlockSize; /*<< The size of the free block. */
} BlockLink_t;
/*-----------------------------------------------------------*/
/*
* Inserts a block of memory that is being freed into the correct position in
* the list of free memory blocks. The block being freed will be merged with
* the block in front it and/or the block behind it if the memory blocks are
* adjacent to each other.
*/
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION;
/*
* Called automatically to setup the required heap structures the first time
* pvPortMalloc() is called.
*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
static void prvHeapInit( void ) PRIVILEGED_FUNCTION;
#endif
/*-----------------------------------------------------------*/
/* The size of the structure placed at the beginning of each allocated memory
* block must by correctly byte aligned. */
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
/* Create a couple of list links to mark the start and end of the list. */
PRIVILEGED_DATA static BlockLink_t xStart, * pxEnd = NULL;
/* Keeps track of the number of calls to allocate and free memory as well as the
* number of free bytes remaining, but says nothing about fragmentation. */
PRIVILEGED_DATA static size_t xFreeBytesRemaining = 0U;
PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = 0U;
PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = 0;
PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = 0;
/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize
* member of an BlockLink_t structure is set then the block belongs to the
* application. When the bit is free the block is still part of the free heap
* space. */
PRIVILEGED_DATA static size_t xBlockAllocatedBit = 0;
/*-----------------------------------------------------------*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS == 0)
void * UTIL_MM_GetBuffer( size_t xWantedSize )
#else
void * pvPortMalloc( size_t xWantedSize )
#endif
{
BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink;
void * pvReturn = NULL;
vTaskSuspendAll();
{
/* If this is the first call to malloc then the heap will require
* initialisation to setup the list of free blocks. */
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
if( pxEnd == NULL )
{
prvHeapInit();
}
else
#endif
{
mtCOVERAGE_TEST_MARKER();
}
/* Check the requested block size is not so large that the top bit is
* set. The top bit of the block size member of the BlockLink_t structure
* is used to determine who owns the block - the application or the
* kernel, so it must be free. */
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
{
/* The wanted size is increased so it can contain a BlockLink_t
* structure in addition to the requested amount of bytes. */
if( xWantedSize > 0 )
{
xWantedSize += xHeapStructSize;
/* Ensure that blocks are always aligned to the required number
* of bytes. */
if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 )
{
/* Byte alignment required. */
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
{
/* Traverse the list from the start (lowest address) block until
* one of adequate size is found. */
pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
pxBlock = pxBlock->pxNextFreeBlock;
}
/* If the end marker was reached then a block of adequate size
* was not found. */
if( pxBlock != pxEnd )
{
/* Return the memory space pointed to - jumping over the
* BlockLink_t structure at its start. */
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
/* This block is being returned for use so must be taken out
* of the list of free blocks. */
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
/* If the block is larger than required it can be split into
* two. */
if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
{
/* This block is to be split into two. Create a new
* block following the number of bytes requested. The void
* cast is used to prevent byte alignment warnings from the
* compiler. */
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 );
/* Calculate the sizes of two blocks split from the
* single block. */
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
pxBlock->xBlockSize = xWantedSize;
/* Insert the new block into the list of free blocks. */
prvInsertBlockIntoFreeList( pxNewBlockLink );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
xFreeBytesRemaining -= pxBlock->xBlockSize;
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
{
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* The block is being returned - it is allocated and owned
* by the application and has no "next" block. */
pxBlock->xBlockSize |= xBlockAllocatedBit;
pxBlock->pxNextFreeBlock = NULL;
xNumberOfSuccessfulAllocations++;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
traceMALLOC( pvReturn, xWantedSize );
}
( void ) xTaskResumeAll();
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )
{
if( pvReturn == NULL )
{
extern void vApplicationMallocFailedHook( void );
vApplicationMallocFailedHook();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
#endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */
configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn;
}
/*-----------------------------------------------------------*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS == 0)
void UTIL_MM_ReleaseBuffer( void * pv )
#else
void vPortFree( void * pv )
#endif
{
uint8_t * puc = ( uint8_t * ) pv;
BlockLink_t * pxLink;
if( pv != NULL )
{
/* The memory being freed will have an BlockLink_t structure immediately
* before it. */
puc -= xHeapStructSize;
/* This casting is to keep the compiler from issuing warnings. */
pxLink = ( void * ) puc;
/* Check the block is actually allocated. */
configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
configASSERT( pxLink->pxNextFreeBlock == NULL );
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
{
if( pxLink->pxNextFreeBlock == NULL )
{
/* The block is being returned to the heap - it is no longer
* allocated. */
pxLink->xBlockSize &= ~xBlockAllocatedBit;
vTaskSuspendAll();
{
/* Add this block to the list of free blocks. */
xFreeBytesRemaining += pxLink->xBlockSize;
traceFREE( pv, pxLink->xBlockSize );
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
xNumberOfSuccessfulFrees++;
}
( void ) xTaskResumeAll();
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
}
/*-----------------------------------------------------------*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
size_t xPortGetFreeHeapSize( void )
{
return xFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
size_t xPortGetMinimumEverFreeHeapSize( void )
{
return xMinimumEverFreeBytesRemaining;
}
/*-----------------------------------------------------------*/
void vPortInitialiseBlocks( void )
{
/* This just exists to keep the linker quiet. */
}
/*-----------------------------------------------------------*/
static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */
#else
void UTIL_MM_Init(uint8_t *p_pool, uint32_t pool_size)
#endif
{
BlockLink_t * pxFirstFreeBlock;
uint8_t * pucAlignedHeap;
size_t uxAddress;
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;
#else
size_t xTotalHeapSize;
xTotalHeapSize = pool_size;
#endif
/* Ensure the heap starts on a correctly aligned boundary. */
uxAddress = ( size_t ) p_pool;
if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
{
uxAddress += ( portBYTE_ALIGNMENT - 1 );
uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
xTotalHeapSize -= uxAddress - ( size_t ) p_pool;
}
pucAlignedHeap = ( uint8_t * ) uxAddress;
/* xStart is used to hold a pointer to the first item in the list of free
* blocks. The void cast is used to prevent compiler warnings. */
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
xStart.xBlockSize = ( size_t ) 0;
/* pxEnd is used to mark the end of the list of free blocks and is inserted
* at the end of the heap space. */
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
uxAddress -= xHeapStructSize;
uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
pxEnd = ( void * ) uxAddress;
pxEnd->xBlockSize = 0;
pxEnd->pxNextFreeBlock = NULL;
/* To start with there is a single free block that is sized to take up the
* entire heap space, minus the space taken by pxEnd. */
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
/* Only one block exists - and it covers the entire usable heap space. */
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
/* Work out the position of the top bit in a size_t variable. */
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
}
/*-----------------------------------------------------------*/
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */
{
BlockLink_t * pxIterator;
uint8_t * puc;
/* Iterate through the list until a block is found that has a higher address
* than the block being inserted. */
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
{
/* Nothing to do here, just iterate to the right position. */
}
/* Do the block being inserted, and the block it is being inserted after
* make a contiguous block of memory? */
puc = ( uint8_t * ) pxIterator;
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
{
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
pxBlockToInsert = pxIterator;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
/* Do the block being inserted, and the block it is being inserted before
* make a contiguous block of memory? */
puc = ( uint8_t * ) pxBlockToInsert;
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
{
if( pxIterator->pxNextFreeBlock != pxEnd )
{
/* Form one big block from the two blocks. */
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
}
else
{
pxBlockToInsert->pxNextFreeBlock = pxEnd;
}
}
else
{
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
}
/* If the block being inserted plugged a gab, so was merged with the block
* before and the block after, then it's pxNextFreeBlock pointer will have
* already been set, and should not be set here as that would make it point
* to itself. */
if( pxIterator != pxBlockToInsert )
{
pxIterator->pxNextFreeBlock = pxBlockToInsert;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
/*-----------------------------------------------------------*/
#if (KEEP_ORIGINAL_CODE_FROM_FREERTOS != 0)
void vPortGetHeapStats( HeapStats_t * pxHeapStats )
{
BlockLink_t * pxBlock;
size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */
vTaskSuspendAll();
{
pxBlock = xStart.pxNextFreeBlock;
/* pxBlock will be NULL if the heap has not been initialised. The heap
* is initialised automatically when the first allocation is made. */
if( pxBlock != NULL )
{
do
{
/* Increment the number of blocks and record the largest block seen
* so far. */
xBlocks++;
if( pxBlock->xBlockSize > xMaxSize )
{
xMaxSize = pxBlock->xBlockSize;
}
if( pxBlock->xBlockSize < xMinSize )
{
xMinSize = pxBlock->xBlockSize;
}
/* Move to the next block in the chain until the last block is
* reached. */
pxBlock = pxBlock->pxNextFreeBlock;
} while( pxBlock != pxEnd );
}
}
( void ) xTaskResumeAll();
pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
pxHeapStats->xNumberOfFreeBlocks = xBlocks;
taskENTER_CRITICAL();
{
pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
}
taskEXIT_CRITICAL();
}
#endif

View File

@@ -0,0 +1,64 @@
/**
******************************************************************************
* @file stm32_mm.h
* @author MCD Application Team
* @brief Header for stm32_mm.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32_MM_H
#define STM32_MM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported defines -----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
/**
* @brief Initialize the Pool
* @param p_pool: The pool of memory to manage
* @param pool_size: The size of the pool
* @retval None
*/
void UTIL_MM_Init(uint8_t *p_pool, uint32_t pool_size);
/**
* @brief Provide a buffer
* @param xWantedSize: The size of the buffer requested
* @retval The buffer address when available or NULL when there is no buffer
*/
void * UTIL_MM_GetBuffer(size_t xWantedSize);
/**
* @brief Release a buffer
* @param pv: The data buffer address
* @retval None
*/
void UTIL_MM_ReleaseBuffer( void * pv );
/* Exported functions to be implemented by the user if required ------------- */
#ifdef __cplusplus
}
#endif
#endif /* STM32_MM_H */

View File

@@ -0,0 +1,85 @@
/**
******************************************************************************
* @file rf_antenna_switch.c
* @author MCD Application Team
* @brief RF related module to handle dedictated GPIOs for antenna switch
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "rf_antenna_switch.h"
#include "ll_intf.h"
#include "app_conf.h"
#if (SUPPORT_AOA_AOD == 1) || (SUPPORT_ANT_DIV == 1)
static void RF_CONTROL_AntennaSwitch_Enable(void);
static void RF_CONTROL_AntennaSwitch_Disable(void);
static void RF_CONTROL_AntennaSwitch_Enable(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
uint32_t table_size = sizeof(rt_antenna_switch_gpio_table)/sizeof(rt_antenna_switch_gpio_table[0]);
for(unsigned int cpt = 0; cpt<table_size; cpt++)
{
GPIO_InitStruct.Pin = rt_antenna_switch_gpio_table[cpt].GPIO_pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = rt_antenna_switch_gpio_table[cpt].GPIO_alternate;
HAL_GPIO_Init(rt_antenna_switch_gpio_table[cpt].GPIO_port, &GPIO_InitStruct);
}
}
static void RF_CONTROL_AntennaSwitch_Disable(void)
{
uint32_t table_size = sizeof(rt_antenna_switch_gpio_table)/sizeof(rt_antenna_switch_gpio_table[0]);
for(unsigned int cpt = 0; cpt<table_size; cpt++)
{
HAL_GPIO_DeInit(rt_antenna_switch_gpio_table[cpt].GPIO_port, rt_antenna_switch_gpio_table[cpt].GPIO_pin);
}
}
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state)
{
#if (SUPPORT_AOA_AOD == 1)
ble_stat_t status = GENERAL_FAILURE;
#endif
if(state == RF_ANTSW_ENABLE)
{
#if (SUPPORT_AOA_AOD == 1)
status = ll_intf_set_num_of_antennas(CFG_RADIO_NUM_OF_ANTENNAS);
if(status != SUCCESS)
{
/* Specified number of antennas is not supported */
assert_param(0);
return;
}
#endif /* SUPPORT_AOA_AOD */
RF_CONTROL_AntennaSwitch_Enable();
}
else
{
RF_CONTROL_AntennaSwitch_Disable();
}
}
#else /* SUPPORT_AOA_AOD || SUPPORT_ANT_DIV */
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state)
{
/* AoA-AoD or antenna diversity feature is not supported with this Link Layer configuration */
assert_param(0);
}
#endif /* SUPPORT_AOA_AOD || SUPPORT_ANT_DIV */

View File

@@ -0,0 +1,56 @@
/**
******************************************************************************
* @file rf_antenna_switch.h
* @author MCD Application Team
* @brief RF related module to handle dedictated GPIOs for antenna switch
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef RF_ANTENNA_SWITCH_H
#define RF_ANTENNA_SWITCH_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32wbaxx.h"
#define RF_ANTSW0 {GPIOA, GPIO_PIN_12, GPIO_AF11_RF_ANTSW0}
#define RF_ANTSW1 {GPIOA, GPIO_PIN_11, GPIO_AF11_RF_ANTSW1}
#define RF_ANTSW2 {GPIOB, GPIO_PIN_2, GPIO_AF11_RF_ANTSW2}
typedef struct {
GPIO_TypeDef* GPIO_port;
uint16_t GPIO_pin;
uint8_t GPIO_alternate;
} st_gpio_antsw_t;
typedef enum {
RF_ANTSW_DISABLE = 0,
RF_ANTSW_ENABLE
} rf_antenna_switch_state_t;
static const st_gpio_antsw_t rt_antenna_switch_gpio_table[] =
{
RF_ANTSW0,
RF_ANTSW1,
RF_ANTSW2
};
void RF_CONTROL_AntennaSwitch(rf_antenna_switch_state_t state);
#ifdef __cplusplus
}
#endif
#endif /* RF_ANTENNA_SWITCH_H */

View File

@@ -0,0 +1,89 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rf_external_pa.c
* @author MCD Application Team
* @brief RF related module to handle dedictated GPIOs for external PA
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#include "rf_external_pa.h"
#include "power_table.h"
#include "ll_intf.h"
#include "app_conf.h"
static void RF_CONTROL_ExternalPA_Enable(void);
static void RF_CONTROL_ExternalPA_Disable(void);
static uint8_t RF_CONTROL_ExternalPA_Enable_cb(uint8_t epa_enable);
static void RF_CONTROL_ExternalPA_Enable(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
uint32_t table_size = sizeof(rf_external_pa_gpio_table)/sizeof(rf_external_pa_gpio_table[0]);
for(unsigned int cpt = 0; cpt<table_size; cpt++)
{
GPIO_InitStruct.Pin = rf_external_pa_gpio_table[cpt].GPIO_pin;
GPIO_InitStruct.Mode = rf_external_pa_gpio_table[cpt].GPIO_mode;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = rf_external_pa_gpio_table[cpt].GPIO_alternate;
HAL_GPIO_Init(rf_external_pa_gpio_table[cpt].GPIO_port, &GPIO_InitStruct);
}
}
static void RF_CONTROL_ExternalPA_Disable(void)
{
uint32_t table_size = sizeof(rf_external_pa_gpio_table)/sizeof(rf_external_pa_gpio_table[0]);
for(unsigned int cpt = 0; cpt<table_size; cpt++)
{
HAL_GPIO_DeInit(rf_external_pa_gpio_table[cpt].GPIO_port, rf_external_pa_gpio_table[cpt].GPIO_pin);
}
}
static uint8_t RF_CONTROL_ExternalPA_Enable_cb(uint8_t epa_enable)
{
if(epa_enable == 1)
{
HAL_GPIO_WritePin(rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_port, rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_pin, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_port, rf_external_pa_gpio_table[RF_EPA_SIGNAL_CSD].GPIO_pin, GPIO_PIN_RESET);
}
return 0;
}
void RF_CONTROL_ExternalPA(rf_external_pa_state_t state)
{
ble_stat_t status = GENERAL_FAILURE;
if(state == RF_EPA_ENABLE)
{
status = ll_tx_pwr_if_epa_init(1, RF_CONTROL_ExternalPA_Enable_cb);
if(status != SUCCESS)
{
/* EPA callback is not defined */
assert_param(0);
return;
}
RF_CONTROL_ExternalPA_Enable();
}
else
{
RF_CONTROL_ExternalPA_Disable();
}
}

View File

@@ -0,0 +1,61 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rf_external_pa.h
* @author MCD Application Team
* @brief RF related module to handle dedictated GPIOs for external PA
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#ifndef RF_EXTERNAL_PA_H
#define RF_EXTERNAL_PA_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32wbaxx.h"
#define RF_EPA_CSD {GPIOA, GPIO_PIN_9, GPIO_MODE_OUTPUT_PP, GPIO_AF15_EVENTOUT}
#define RF_EPA_CTX {GPIOB, GPIO_PIN_15, GPIO_MODE_AF_PP, GPIO_AF11_RF_IO1}
typedef struct {
GPIO_TypeDef* GPIO_port;
uint16_t GPIO_pin;
uint32_t GPIO_mode;
uint8_t GPIO_alternate;
} st_gpio_epa_t;
typedef enum {
RF_EPA_DISABLE = 0,
RF_EPA_ENABLE
} rf_external_pa_state_t;
typedef enum {
RF_EPA_SIGNAL_CSD = 0,
RF_EPA_SIGNAL_CTX
} rf_external_pa_signal_t;
static const st_gpio_epa_t rf_external_pa_gpio_table[] =
{
[RF_EPA_SIGNAL_CSD] = RF_EPA_CSD,
[RF_EPA_SIGNAL_CTX] = RF_EPA_CTX
};
void RF_CONTROL_ExternalPA(rf_external_pa_state_t state);
#ifdef __cplusplus
}
#endif
#endif /* RF_EXTERNAL_PA_H */

View File

@@ -0,0 +1,79 @@
/**
******************************************************************************
* @file RTDebug.c
* @author MCD Application Team
* @brief Real Time Debug module API definition
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#include "RTDebug.h"
#include "local_debug_tables.h"
#include "stm32wbaxx_hal.h"
#include <assert.h>
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
static_assert((sizeof(general_debug_table)/sizeof(st_gpio_debug_t)) == RT_DEBUG_SIGNALS_TOTAL_NUM,
"Debug signals number is different from debug signal table size."
);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
/***********************/
/** System debug APIs **/
/***********************/
void SYSTEM_DEBUG_SIGNAL_SET(system_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_SET(signal, system_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}
void SYSTEM_DEBUG_SIGNAL_RESET(system_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_RESET(signal, system_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}
void SYSTEM_DEBUG_SIGNAL_TOGGLE(system_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_TOGGLE(signal, system_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}
/***************************/
/** Link Layer debug APIs **/
/***************************/
/* Link Layer debug API definition */
void LINKLAYER_DEBUG_SIGNAL_SET(linklayer_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_SET(signal, linklayer_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}
void LINKLAYER_DEBUG_SIGNAL_RESET(linklayer_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_RESET(signal, linklayer_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}
void LINKLAYER_DEBUG_SIGNAL_TOGGLE(linklayer_debug_signal_t signal)
{
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
GENERIC_DEBUG_GPIO_TOGGLE(signal, linklayer_debug_table);
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
}

View File

@@ -0,0 +1,93 @@
/**
******************************************************************************
* @file RTDebug.h
* @author MCD Application Team
* @brief Real Time Debug module API declaration
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef SYSTEM_DEBUG_H
#define SYSTEM_DEBUG_H
#ifdef __cplusplus
extern "C" {
#endif
#include "debug_config.h"
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
/**************************************************************/
/** Generic macros for local signal table index recuperation **/
/** and global signal table GPIO manipulation **/
/**************************************************************/
#define GENERIC_DEBUG_GPIO_SET(signal, table) do { \
uint32_t debug_table_idx = 0; \
if(signal >= sizeof(table)) \
{ \
return; \
} \
debug_table_idx = table[signal]; \
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
{ \
LL_GPIO_SetOutputPin(general_debug_table[debug_table_idx].GPIO_port, \
general_debug_table[debug_table_idx].GPIO_pin); \
} \
} while(0)
#define GENERIC_DEBUG_GPIO_RESET(signal, table) do { \
uint32_t debug_table_idx = 0; \
if(signal >= sizeof(table)) \
{ \
return; \
} \
debug_table_idx = table[signal]; \
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
{ \
LL_GPIO_ResetOutputPin(general_debug_table[debug_table_idx].GPIO_port, \
general_debug_table[debug_table_idx].GPIO_pin); \
} \
} while(0)
#define GENERIC_DEBUG_GPIO_TOGGLE(signal, table) do { \
uint32_t debug_table_idx = 0; \
if(signal >= sizeof(table)) \
{ \
return; \
} \
debug_table_idx = table[signal]; \
if(debug_table_idx != RT_DEBUG_SIGNAL_UNUSED) \
{ \
LL_GPIO_TogglePin(general_debug_table[debug_table_idx].GPIO_port, \
general_debug_table[debug_table_idx].GPIO_pin); \
} \
} while(0)
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
/* System debug API definition */
void SYSTEM_DEBUG_SIGNAL_SET(system_debug_signal_t signal);
void SYSTEM_DEBUG_SIGNAL_RESET(system_debug_signal_t signal);
void SYSTEM_DEBUG_SIGNAL_TOGGLE(system_debug_signal_t signal);
/* Link Layer debug API definition */
void LINKLAYER_DEBUG_SIGNAL_SET(linklayer_debug_signal_t signal);
void LINKLAYER_DEBUG_SIGNAL_RESET(linklayer_debug_signal_t signal);
void LINKLAYER_DEBUG_SIGNAL_TOGGLE(linklayer_debug_signal_t signal);
#ifdef __cplusplus
}
#endif
#endif /* SYSTEM_DEBUG_H */

View File

@@ -0,0 +1,147 @@
/**
******************************************************************************
* @file RTDebug_dtb.c
* @author MCD Application Team
* @brief Real Time Debug module API definition for DTB usage
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/**
* The DEBUG DTB interface is INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT.
* It provides HW signals from RF PHY activity.
*/
/* Includes ------------------------------------------------------------------*/
#include "RTDebug_dtb.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#if(CFG_RT_DEBUG_DTB == 1)
/* Private function prototypes -----------------------------------------------*/
static void RT_DEBUG_SetDTBMode(uint8_t dtb, uint8_t mode);
/* Private functions ---------------------------------------------------------*/
static void RT_DEBUG_SetDTBMode(uint8_t dtb, uint8_t mode)
{
/* Set SYSCFG for DTB */
uint32_t addr = (uint32_t)(&SYSCFG->SECCFGR);
__HAL_RCC_SYSCFG_CLK_ENABLE();
addr += 0x100; /* contains SYSCFG->DBTCR address */
/* Keep others DTB in current modes */
*(uint32_t*)addr |= (0xF<<(dtb*4)); /* Selected DTB unmask mode */
*(uint32_t*)addr ^= (0xF<<(dtb*4)); /* Selected DTB unset mode */
/* Selected DTB set to mode */
*(uint32_t*)addr |= (mode<<(dtb*4));
}
void RT_DEBUG_DTBInit(void)
{
/** access_match PA7 DTB[7] on TL_10 **/
/*
LL_GPIO_SetPinSpeed(GPIOA,LL_GPIO_PIN_7,LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_7,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_7,LL_GPIO_AF_15);
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_7);
*/
/** long_range_iq_vld PA6 DTB[6] on TL_9 **/
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_6,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_6,LL_GPIO_AF_15);
/** tx_data PA5 DTB[5] on TL_8 **/
/*
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_5,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_5,LL_GPIO_AF_15);
*/
/** rx_data PB9 DTB[4] on TL_31 **/
/*
LL_GPIO_SetPinMode(GPIOB,LL_GPIO_PIN_9,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(GPIOB,LL_GPIO_PIN_9,LL_GPIO_AF_15);
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTB, LL_PWR_GPIO_PIN_9);
*/
/** tx_data_clk PB8 DTB[3] on TL_30 **/
/*
LL_GPIO_SetPinMode(GPIOB,LL_GPIO_PIN_8,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(GPIOB,LL_GPIO_PIN_8,LL_GPIO_AF_15);
*/
/** rx_data_clk PA2 DTB[2] on TL_3 **/
/*
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_2,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_2,LL_GPIO_AF_15);
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_2);
*/
/** tx_on PA1 DTB[1] on TL_2 **/
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_1,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_1,LL_GPIO_AF_15);
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_1);
/** rx_on PA0 DTB[0] on TL_1 **/
/*
LL_GPIO_SetPinMode(GPIOA,LL_GPIO_PIN_0,LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_0_7(GPIOA,LL_GPIO_PIN_0,LL_GPIO_AF_15);
LL_PWR_EnableGPIOStandbyRetention(LL_PWR_GPIO_STATE_RETENTION_ENABLE_PORTA, LL_PWR_GPIO_PIN_0);
*/
/* Set SYSCFG for DTB */
uint32_t addr = (uint32_t)(&SYSCFG->SECCFGR);
__HAL_RCC_SYSCFG_CLK_ENABLE();
addr += 0x100; /* contains SYSCFG->DBTCR address */
/* Default DTB in test mode 0 */
*(uint32_t*)addr = 0x00000000;
}
/* Public functions ----------------------------------------------------------*/
void RT_DEBUG_DTBConfig(void)
{
/*
** Monitor DTB **
* A0 o PA0 AF15 DTB[0] mode 1 rx_on
* A1 o PA1 AF15 DTB[1] mode 1 tx_on
* A2 o PB9 AF15 DTB[4] mode 5 radio_bbclk
* A3 o PA7 AF15 DTB[7] mode 3 slptmr_irq
* A4 o PA2 AF15 DTB[2] mode 5 CM33_sleepdeep
* A5 o PA6 AF00 PWR_CSTOP
* A6 o PA8 as SYSclk source
* A7 o PB1 Monitor wakeup GPIO
* A8 o PB0 Debug PIN
* A9 o PC0 o_pm_sleep_sw
* A10 o PC1 o_pm_act_com_sw
**/
RT_DEBUG_SetDTBMode(6, 3) ; /* Radio IRQ */
RT_DEBUG_SetDTBMode(1, 1); /* tx_on */
//RT_DEBUG_SetDTBMode(0, 1); /* rx_on */
//RT_DEBUG_SetDTBMode(1, 3); /* sleep timer irq */
//RT_DEBUG_SetDTBMode(2, 5); /* CM33_sleepdeep */
//RT_DEBUG_SetDTBMode(4, 5); /* radio_bbclk */
//RT_DEBUG_SetDTBMode(7, 3); /* slptm_irq */
//RT_DEBUG_SetDTBMode(7, 5); /* radio_bus_clk */
//RT_DEBUG_SetDTBMode(7, 6); /* test tm 00 */
//RT_DEBUG_SetDTBMode(6, 6); /* test tm 01 */
}
#endif /* CFG_RT_DEBUG_DTB */

View File

@@ -0,0 +1,43 @@
/**
******************************************************************************
* @file RTDebug_dtb.h
* @author MCD Application Team
* @brief Real Time Debug module API declaration for DTB usage
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef RT_DEBUG_DTB_H
#define RT_DEBUG_DTB_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* The DEBUG DTB interface is INTENDED TO BE USED ONLY ON REQUEST FROM ST SUPPORT.
* It provides HW signals from RF PHY activity.
*/
#include "app_conf.h"
#if(CFG_RT_DEBUG_DTB == 1)
void RT_DEBUG_DTBConfig(void);
void RT_DEBUG_DTBInit(void);
#endif /* CFG_RT_DEBUG_DTB */
#ifdef __cplusplus
}
#endif
#endif /* RT_DEBUG_DTB_H */

View File

@@ -0,0 +1,833 @@
/**
******************************************************************************
* @file debug_signals.h
* @author MCD Application Team
* @brief Real Time Debug module System and Link Layer signal definition
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef DEBUG_SIGNALS_H
#define DEBUG_SIGNALS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "bsp.h"
/**************************************************/
/** Specific Link Layer debug signals definition **/
/**************************************************/
typedef Debug_GPIO_t linklayer_debug_signal_t;
/**********************************************/
/** Specific System debug signals definition **/
/**********************************************/
typedef enum {
ADC_ACTIVATION,
ADC_DEACTIVATION,
ADC_TEMPERATURE_ACQUISITION,
RNG_ENABLE,
RNG_DISABLE,
RNG_GEN_RAND_NUM,
LOW_POWER_STOP_MODE_ENTER,
LOW_POWER_STOP_MODE_EXIT,
LOW_POWER_STOP_MODE_ACTIVE,
LOW_POWER_STOP2_MODE_ENTER,
LOW_POWER_STOP2_MODE_EXIT,
LOW_POWER_STOP2_MODE_ACTIVE,
LOW_POWER_STANDBY_MODE_ENTER,
LOW_POWER_STANDBY_MODE_EXIT,
LOW_POWER_STANDBY_MODE_ACTIVE,
SCM_SETUP,
SCM_SYSTEM_CLOCK_CONFIG,
SCM_HSERDY_ISR,
} system_debug_signal_t;
#if(CFG_RT_DEBUG_GPIO_MODULE == 1)
/*************************************/
/** Global debug signals definition **/
/*************************************/
typedef enum {
RT_DEBUG_SIGNAL_UNUSED = 0x0,
/********************/
/** System signals **/
/********************/
#if (USE_RT_DEBUG_SCM_SETUP == 1)
RT_DEBUG_SCM_SETUP,
#endif /* USE_RT_DEBUG_SCM_SETUP */
#if (USE_RT_DEBUG_SCM_HSERDY_ISR == 1)
RT_DEBUG_SCM_HSERDY_ISR,
#endif /* USE_RT_DEBUG_SCM_HSERDY_ISR */
#if (USE_RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG == 1)
RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG,
#endif /* USE_RT_DEBUG_SCM_SYSTEM_CLOCK_CONFIG */
#if (USE_RT_DEBUG_ADC_ACTIVATION == 1)
RT_DEBUG_ADC_ACTIVATION,
#endif /* USE_RT_DEBUG_ADC_ACTIVATION */
#if (USE_RT_DEBUG_ADC_DEACTIVATION == 1)
RT_DEBUG_ADC_DEACTIVATION,
#endif /* USE_RT_DEBUG_ADC_DEACTIVATION */
#if (USE_RT_DEBUG_ADC_TEMPERATURE_ACQUISITION == 1)
RT_DEBUG_ADC_TEMPERATURE_ACQUISITION,
#endif /* USE_RT_DEBUG_ADC_TEMPERATURE_ACQUISITION */
#if (USE_RT_DEBUG_RNG_ENABLE == 1)
RT_DEBUG_RNG_ENABLE,
#endif /* USE_RT_DEBUG_RNG_ENABLE */
#if (USE_RT_DEBUG_RNG_DISABLE == 1)
RT_DEBUG_RNG_DISABLE,
#endif /* USE_RT_DEBUG_RNG_DISABLE */
#if (USE_RT_DEBUG_RNG_GEN_RAND_NUM == 1)
RT_DEBUG_RNG_GEN_RAND_NUM,
#endif /* USE_RT_DEBUG_RNG_GEN_RAND_NUM */
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_ENTER == 1)
RT_DEBUG_LOW_POWER_STOP_MODE_ENTER,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_ENTER */
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_EXIT == 1)
RT_DEBUG_LOW_POWER_STOP_MODE_EXIT,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_EXIT */
#if (USE_RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE == 1)
RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP_MODE_ACTIVE */
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER == 1)
RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ENTER */
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT == 1)
RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_EXIT */
#if (USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE == 1)
RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE,
#endif /* USE_RT_DEBUG_LOW_POWER_STOP2_MODE_ACTIVE */
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER == 1)
RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER,
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ENTER */
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT == 1)
RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT,
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_EXIT */
#if (USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE == 1)
RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE,
#endif /* USE_RT_DEBUG_LOW_POWER_STANDBY_MODE_ACTIVE */
/************************/
/** Link Layer signals **/
/************************/
#if (USE_RT_DEBUG_HCI_READ_DONE == 1)
RT_DEBUG_HCI_READ_DONE,
#endif /* USE_RT_DEBUG_HCI_READ_DONE */
#if (USE_RT_DEBUG_HCI_RCVD_CMD == 1)
RT_DEBUG_HCI_RCVD_CMD,
#endif /* USE_RT_DEBUG_HCI_RCVD_CMD */
#if (USE_RT_DEBUG_HCI_WRITE_DONE == 1)
RT_DEBUG_HCI_WRITE_DONE,
#endif /* USE_RT_DEBUG_HCI_WRITE_DONE */
#if (USE_RT_DEBUG_SCHDLR_EVNT_UPDATE == 1)
RT_DEBUG_SCHDLR_EVNT_UPDATE,
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_UPDATE */
#if (USE_RT_DEBUG_SCHDLR_TIMER_SET == 1)
RT_DEBUG_SCHDLR_TIMER_SET,
#endif /* USE_RT_DEBUG_SCHDLR_TIMER_SET */
#if (USE_RT_DEBUG_SCHDLR_PHY_CLBR_TIMER == 1)
RT_DEBUG_SCHDLR_PHY_CLBR_TIMER,
#endif /* USE_RT_DEBUG_SCHDLR_PHY_CLBR_TIMER */
#if (USE_RT_DEBUG_SCHDLR_EVNT_SKIPPED == 1)
RT_DEBUG_SCHDLR_EVNT_SKIPPED,
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_SKIPPED */
#if (USE_RT_DEBUG_SCHDLR_HNDL_NXT_TRACE == 1)
RT_DEBUG_SCHDLR_HNDL_NXT_TRACE,
#endif /* USE_RT_DEBUG_SCHDLR_HNDL_NXT_TRACE */
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED == 1)
RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED,
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_DETEDTED */
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK == 1)
RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK,
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_GAP_CHECK */
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK == 1)
RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK,
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TIME_CHECK */
#if (USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE == 1)
RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE,
#endif /* USE_RT_DEBUG_ACTIVE_SCHDLR_NEAR_TRACE */
#if (USE_RT_DEBUG_SCHDLR_EVNT_RGSTR == 1)
RT_DEBUG_SCHDLR_EVNT_RGSTR,
#endif /* USE_RT_DEBUG_SCHDLR_EVNT_RGSTR */
#if (USE_RT_DEBUG_SCHDLR_ADD_CONFLICT_Q == 1)
RT_DEBUG_SCHDLR_ADD_CONFLICT_Q,
#endif /* USE_RT_DEBUG_SCHDLR_ADD_CONFLICT_Q */
#if (USE_RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT == 1)
RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT,
#endif /* USE_RT_DEBUG_SCHDLR_HNDL_MISSED_EVNT */
#if (USE_RT_DEBUG_SCHDLR_UNRGSTR_EVNT == 1)
RT_DEBUG_SCHDLR_UNRGSTR_EVNT,
#endif /* USE_RT_DEBUG_SCHDLR_UNRGSTR_EVNT */
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE == 1)
RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE,
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_TRACE */
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE == 1)
RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE,
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_PROFILE */
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR == 1)
RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR,
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_ERROR */
#if (USE_RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING == 1)
RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING,
#endif /* USE_RT_DEBUG_SCHDLR_EXEC_EVNT_WINDOW_WIDENING */
#if (USE_RT_DEBUG_LLHWC_CMN_CLR_ISR == 1)
RT_DEBUG_LLHWC_CMN_CLR_ISR,
#endif /* USE_RT_DEBUG_LLHWC_CMN_CLR_ISR */
#if (USE_RT_DEBUG_LLWCC_CMN_HG_ISR == 1)
RT_DEBUG_LLWCC_CMN_HG_ISR,
#endif /* USE_RT_DEBUG_LLWCC_CMN_HG_ISR */
#if (USE_RT_DEBUG_LLHWC_CMN_LW_ISR == 1)
RT_DEBUG_LLHWC_CMN_LW_ISR,
#endif /* USE_RT_DEBUG_LLHWC_CMN_LW_ISR */
#if (USE_RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR == 1)
RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR,
#endif /* USE_RT_DEBUG_LLHWC_CMN_CLR_TIMER_ERROR */
#if (USE_RT_DEBUG_LLHWC_LL_ISR == 1)
RT_DEBUG_LLHWC_LL_ISR,
#endif /* USE_RT_DEBUG_LLHWC_LL_ISR */
#if (USE_RT_DEBUG_LLHWC_SPLTMR_SET == 1)
RT_DEBUG_LLHWC_SPLTMR_SET,
#endif /* USE_RT_DEBUG_LLHWC_SPLTMR_SET */
#if (USE_RT_DEBUG_LLHWC_SPLTMR_GET == 1)
RT_DEBUG_LLHWC_SPLTMR_GET,
#endif /* USE_RT_DEBUG_LLHWC_SPLTMR_GET */
#if (USE_RT_DEBUG_LLHWC_LOW_ISR == 1)
RT_DEBUG_LLHWC_LOW_ISR,
#endif /* USE_RT_DEBUG_LLHWC_LOW_ISR */
#if (USE_RT_DEBUG_LLHWC_STOP_SCN == 1)
RT_DEBUG_LLHWC_STOP_SCN,
#endif /* USE_RT_DEBUG_LLHWC_STOP_SCN */
#if (USE_RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR == 1)
RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR,
#endif /* USE_RT_DEBUG_LLHWC_WAIT_ENVT_ON_AIR */
#if (USE_RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM == 1)
RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM,
#endif /* USE_RT_DEBUG_LLHWC_SET_CONN_EVNT_PARAM */
#if (USE_RT_DEBUG_POST_EVNT == 1)
RT_DEBUG_POST_EVNT,
#endif /* USE_RT_DEBUG_POST_EVNT */
#if (USE_RT_DEBUG_HNDL_ALL_EVNTS == 1)
RT_DEBUG_HNDL_ALL_EVNTS,
#endif /* USE_RT_DEBUG_HNDL_ALL_EVNTS */
#if (USE_RT_DEBUG_PROCESS_EVNT == 1)
RT_DEBUG_PROCESS_EVNT,
#endif /* USE_RT_DEBUG_PROCESS_EVNT */
#if (USE_RT_DEBUG_PROCESS_ISO_DATA == 1)
RT_DEBUG_PROCESS_ISO_DATA,
#endif /* USE_RT_DEBUG_PROCESS_ISO_DATA */
#if (USE_RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT == 1)
RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT,
#endif /* USE_RT_DEBUG_ALLOC_TX_ISO_EMPTY_PKT */
#if (USE_RT_DEBUG_BIG_FREE_EMPTY_PKTS == 1)
RT_DEBUG_BIG_FREE_EMPTY_PKTS,
#endif /* USE_RT_DEBUG_BIG_FREE_EMPTY_PKTS */
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK == 1)
RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK,
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_OK */
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC == 1)
RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC,
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_CRC */
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX == 1)
RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX,
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_NoRX */
#if (USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE == 1)
RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE,
#endif /* USE_RT_DEBUG_RECOMBINE_UNFRMD_DATA_TRACE */
#if (USE_RT_DEBUG_ISO_HNDL_SDU == 1)
RT_DEBUG_ISO_HNDL_SDU,
#endif /* USE_RT_DEBUG_ISO_HNDL_SDU */
#if (USE_RT_DEBUG_LL_INTF_INIT == 1)
RT_DEBUG_LL_INTF_INIT,
#endif /* USE_RT_DEBUG_LL_INTF_INIT */
#if (USE_RT_DEBUG_DATA_TO_CNTRLR == 1)
RT_DEBUG_DATA_TO_CNTRLR,
#endif /* USE_RT_DEBUG_DATA_TO_CNTRLR */
#if (USE_RT_DEBUG_FREE_LL_PKT_HNDLR == 1)
RT_DEBUG_FREE_LL_PKT_HNDLR,
#endif /* USE_RT_DEBUG_FREE_LL_PKT_HNDLR */
#if (USE_RT_DEBUG_PHY_INIT_CLBR_TRACE == 1)
RT_DEBUG_PHY_INIT_CLBR_TRACE,
#endif /* USE_RT_DEBUG_PHY_INIT_CLBR_TRACE */
#if (USE_RT_DEBUG_PHY_RUNTIME_CLBR_TRACE == 1)
RT_DEBUG_PHY_RUNTIME_CLBR_TRACE,
#endif /* USE_RT_DEBUG_PHY_RUNTIME_CLBR_TRACE */
#if (USE_RT_DEBUG_PHY_CLBR_ISR == 1)
RT_DEBUG_PHY_CLBR_ISR,
#endif /* USE_RT_DEBUG_PHY_CLBR_ISR */
#if (USE_RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH == 1)
RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH,
#endif /* USE_RT_DEBUG_PHY_INIT_CLBR_SINGLE_CH */
#if (USE_RT_DEBUG_PHY_CLBR_STRTD == 1)
RT_DEBUG_PHY_CLBR_STRTD,
#endif /* USE_RT_DEBUG_PHY_CLBR_STRTD */
#if (USE_RT_DEBUG_PHY_CLBR_EXEC == 1)
RT_DEBUG_PHY_CLBR_EXEC,
#endif /* USE_RT_DEBUG_PHY_CLBR_EXEC */
#if (USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV == 1)
RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV,
#endif /* USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_CLBR_ACTV */
#if (USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR == 1)
RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR,
#endif /* USE_RT_DEBUG_RCO_STRT_STOP_RUNTIME_RCO_CLBR */
#if (USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT == 1)
RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT,
#endif /* USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_SWT */
#if (USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE == 1)
RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE,
#endif /* USE_RT_DEBUG_STRT_STOP_RUNTIME_RCO_CLBR_TRACE */
#if (USE_RT_DEBUG_RCO_ISR_TRACE == 1)
RT_DEBUG_RCO_ISR_TRACE,
#endif /* USE_RT_DEBUG_RCO_ISR_TRACE */
#if (USE_RT_DEBUG_RCO_ISR_COMPENDATE == 1)
RT_DEBUG_RCO_ISR_COMPENDATE,
#endif /* USE_RT_DEBUG_RCO_ISR_COMPENDATE */
#if (USE_RT_DEBUG_RAL_STRT_TX == 1)
RT_DEBUG_RAL_STRT_TX,
#endif /* USE_RT_DEBUG_RAL_STRT_TX */
#if (USE_RT_DEBUG_RAL_ISR_TIMER_ERROR == 1)
RT_DEBUG_RAL_ISR_TIMER_ERROR,
#endif /* USE_RT_DEBUG_RAL_ISR_TIMER_ERROR */
#if (USE_RT_DEBUG_RAL_ISR_TRACE == 1)
RT_DEBUG_RAL_ISR_TRACE,
#endif /* USE_RT_DEBUG_RAL_ISR_TRACE */
#if (USE_RT_DEBUG_RAL_STOP_OPRTN == 1)
RT_DEBUG_RAL_STOP_OPRTN,
#endif /* USE_RT_DEBUG_RAL_STOP_OPRTN */
#if (USE_RT_DEBUG_RAL_STRT_RX == 1)
RT_DEBUG_RAL_STRT_RX,
#endif /* USE_RT_DEBUG_RAL_STRT_RX */
#if (USE_RT_DEBUG_RAL_DONE_CLBK_TX == 1)
RT_DEBUG_RAL_DONE_CLBK_TX,
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_TX */
#if (USE_RT_DEBUG_RAL_DONE_CLBK_RX == 1)
RT_DEBUG_RAL_DONE_CLBK_RX,
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_RX */
#if (USE_RT_DEBUG_RAL_DONE_CLBK_ED == 1)
RT_DEBUG_RAL_DONE_CLBK_ED,
#endif /* USE_RT_DEBUG_RAL_DONE_CLBK_ED */
#if (USE_RT_DEBUG_RAL_ED_SCAN == 1)
RT_DEBUG_RAL_ED_SCAN,
#endif /* USE_RT_DEBUG_RAL_ED_SCAN */
#if (USE_RT_DEBUG_ERROR_MEM_CAP_EXCED == 1)
RT_DEBUG_ERROR_MEM_CAP_EXCED,
#endif /* USE_RT_DEBUG_ERROR_MEM_CAP_EXCED */
#if (USE_RT_DEBUG_ERROR_COMMAND_DISALLOWED == 1)
RT_DEBUG_ERROR_COMMAND_DISALLOWED,
#endif /* USE_RT_DEBUG_ERROR_COMMAND_DISALLOWED */
#if (USE_RT_DEBUG_PTA_INIT == 1)
RT_DEBUG_PTA_INIT,
#endif /* USE_RT_DEBUG_PTA_INIT */
#if (USE_RT_DEBUG_PTA_EN == 1)
RT_DEBUG_PTA_EN,
#endif /* USE_RT_DEBUG_PTA_EN */
#if (USE_RT_DEBUG_LLHWC_PTA_SET_EN == 1)
RT_DEBUG_LLHWC_PTA_SET_EN,
#endif /* USE_RT_DEBUG_LLHWC_PTA_SET_EN */
#if (USE_RT_DEBUG_LLHWC_PTA_SET_PARAMS == 1)
RT_DEBUG_LLHWC_PTA_SET_PARAMS,
#endif /* USE_RT_DEBUG_LLHWC_PTA_SET_PARAMS */
#if (USE_RT_DEBUG_COEX_STRT_ON_IDLE == 1)
RT_DEBUG_COEX_STRT_ON_IDLE,
#endif /* USE_RT_DEBUG_COEX_STRT_ON_IDLE */
#if (USE_RT_DEBUG_COEX_ASK_FOR_AIR == 1)
RT_DEBUG_COEX_ASK_FOR_AIR,
#endif /* USE_RT_DEBUG_COEX_ASK_FOR_AIR */
#if (USE_RT_DEBUG_COEX_TIMER_EVNT_CLBK == 1)
RT_DEBUG_COEX_TIMER_EVNT_CLBK,
#endif /* USE_RT_DEBUG_COEX_TIMER_EVNT_CLBK */
#if (USE_RT_DEBUG_COEX_STRT_ONE_SHOT == 1)
RT_DEBUG_COEX_STRT_ONE_SHOT,
#endif /* USE_RT_DEBUG_COEX_STRT_ONE_SHOT */
#if (USE_RT_DEBUG_COEX_FORCE_STOP_RX == 1)
RT_DEBUG_COEX_FORCE_STOP_RX,
#endif /* USE_RT_DEBUG_COEX_FORCE_STOP_RX */
#if (USE_RT_DEBUG_LLHWC_ADV_DONE == 1)
RT_DEBUG_LLHWC_ADV_DONE,
#endif /* USE_RT_DEBUG_LLHWC_ADV_DONE */
#if (USE_RT_DEBUG_LLHWC_SCN_DONE == 1)
RT_DEBUG_LLHWC_SCN_DONE,
#endif /* USE_RT_DEBUG_LLHWC_SCN_DONE */
#if (USE_RT_DEBUG_LLHWC_INIT_DONE == 1)
RT_DEBUG_LLHWC_INIT_DONE,
#endif /* USE_RT_DEBUG_LLHWC_INIT_DONE */
#if (USE_RT_DEBUG_LLHWC_CONN_DONE == 1)
RT_DEBUG_LLHWC_CONN_DONE,
#endif /* USE_RT_DEBUG_LLHWC_CONN_DONE */
#if (USE_RT_DEBUG_LLHWC_CIG_DONE == 1)
RT_DEBUG_LLHWC_CIG_DONE,
#endif /* USE_RT_DEBUG_LLHWC_CIG_DONE */
#if (USE_RT_DEBUG_LLHWC_BIG_DONE == 1)
RT_DEBUG_LLHWC_BIG_DONE,
#endif /* USE_RT_DEBUG_LLHWC_BIG_DONE */
#if (USE_RT_DEBUG_OS_TMR_CREATE == 1)
RT_DEBUG_OS_TMR_CREATE,
#endif /* USE_RT_DEBUG_OS_TMR_CREATE */
#if (USE_RT_DEBUG_ADV_EXT_TIMEOUT_CBK == 1)
RT_DEBUG_ADV_EXT_TIMEOUT_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_TIMEOUT_CBK */
#if (USE_RT_DEBUG_ADV_EXT_SCN_DUR_CBK == 1)
RT_DEBUG_ADV_EXT_SCN_DUR_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_SCN_DUR_CBK */
#if (USE_RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK == 1)
RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_SCN_PERIOD_CBK */
#if (USE_RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK == 1)
RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_PRDC_SCN_TIMEOUT_CBK */
#if (USE_RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK == 1)
RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK,
#endif /* USE_RT_DEBUG_BIS_SYNC_TIMEOUT_TMR_CBK */
#if (USE_RT_DEBUG_BIS_TERM_TMR_CBK == 1)
RT_DEBUG_BIS_TERM_TMR_CBK,
#endif /* USE_RT_DEBUG_BIS_TERM_TMR_CBK */
#if (USE_RT_DEBUG_BIS_TST_MODE_CBK == 1)
RT_DEBUG_BIS_TST_MODE_CBK,
#endif /* USE_RT_DEBUG_BIS_TST_MODE_CBK */
#if (USE_RT_DEBUG_BIS_TST_MODE_TMR_CBK == 1)
RT_DEBUG_BIS_TST_MODE_TMR_CBK,
#endif /* USE_RT_DEBUG_BIS_TST_MODE_TMR_CBK */
#if (USE_RT_DEBUG_ISO_POST_TMR_CBK == 1)
RT_DEBUG_ISO_POST_TMR_CBK,
#endif /* USE_RT_DEBUG_ISO_POST_TMR_CBK */
#if (USE_RT_DEBUG_ISO_TST_MODE_TMR_CBK == 1)
RT_DEBUG_ISO_TST_MODE_TMR_CBK,
#endif /* USE_RT_DEBUG_ISO_TST_MODE_TMR_CBK */
#if (USE_RT_DEBUG_CONN_POST_TMR_CBK == 1)
RT_DEBUG_CONN_POST_TMR_CBK,
#endif /* USE_RT_DEBUG_CONN_POST_TMR_CBK */
#if (USE_RT_DEBUG_EVNT_SCHDLR_TMR_CBK == 1)
RT_DEBUG_EVNT_SCHDLR_TMR_CBK,
#endif /* USE_RT_DEBUG_EVNT_SCHDLR_TMR_CBK */
#if (USE_RT_DEBUG_HCI_POST_TMR_CBK == 1)
RT_DEBUG_HCI_POST_TMR_CBK,
#endif /* USE_RT_DEBUG_HCI_POST_TMR_CBK */
#if (USE_RT_DEBUG_LLCP_POST_TMR_CBK == 1)
RT_DEBUG_LLCP_POST_TMR_CBK,
#endif /* USE_RT_DEBUG_LLCP_POST_TMR_CBK */
#if (USE_RT_DEBUG_LLHWC_ENRGY_DETECT_CBK == 1)
RT_DEBUG_LLHWC_ENRGY_DETECT_CBK,
#endif /* USE_RT_DEBUG_LLHWC_ENRGY_DETECT_CBK */
#if (USE_RT_DEBUG_PRVCY_POST_TMR_CBK == 1)
RT_DEBUG_PRVCY_POST_TMR_CBK,
#endif /* USE_RT_DEBUG_PRVCY_POST_TMR_CBK */
#if (USE_RT_DEBUG_ANT_PRPR_TMR_CBK == 1)
RT_DEBUG_ANT_PRPR_TMR_CBK,
#endif /* USE_RT_DEBUG_ANT_PRPR_TMR_CBK */
#if (USE_RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK == 1)
RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK,
#endif /* USE_RT_DEBUG_COEX_TMR_FRC_STOP_AIR_GRANT_CBK */
#if (USE_RT_DEBUG_MLME_RX_EN_TMR_CBK == 1)
RT_DEBUG_MLME_RX_EN_TMR_CBK,
#endif /* USE_RT_DEBUG_MLME_RX_EN_TMR_CBK */
#if (USE_RT_DEBUG_MLME_GNRC_TMR_CBK == 1)
RT_DEBUG_MLME_GNRC_TMR_CBK,
#endif /* USE_RT_DEBUG_MLME_GNRC_TMR_CBK */
#if (USE_RT_DEBUG_MIB_JOIN_LST_TMR_CBK == 1)
RT_DEBUG_MIB_JOIN_LST_TMR_CBK,
#endif /* USE_RT_DEBUG_MIB_JOIN_LST_TMR_CBK */
#if (USE_RT_DEBUG_MLME_PWR_PRES_TMR_CBK == 1)
RT_DEBUG_MLME_PWR_PRES_TMR_CBK,
#endif /* USE_RT_DEBUG_MLME_PWR_PRES_TMR_CBK */
#if (USE_RT_DEBUG_PRESISTENCE_TMR_CBK == 1)
RT_DEBUG_PRESISTENCE_TMR_CBK,
#endif /* USE_RT_DEBUG_PRESISTENCE_TMR_CBK */
#if (USE_RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK == 1)
RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK,
#endif /* USE_RT_DEBUG_RADIO_PHY_PRDC_CLBK_TMR_CBK */
#if (USE_RT_DEBUG_RADIO_CSMA_TMR_CBK == 1)
RT_DEBUG_RADIO_CSMA_TMR_CBK,
#endif /* USE_RT_DEBUG_RADIO_CSMA_TMR_CBK */
#if (USE_RT_DEBUG_RADIO_CSL_RCV_TMR_CBK == 1)
RT_DEBUG_RADIO_CSL_RCV_TMR_CBK,
#endif /* USE_RT_DEBUG_RADIO_CSL_RCV_TMR_CBK */
#if (USE_RT_DEBUG_ED_TMR_CBK == 1)
RT_DEBUG_ED_TMR_CBK,
#endif /* USE_RT_DEBUG_ED_TMR_CBK */
#if (USE_RT_DEBUG_DIO_EXT_TMR_CBK == 1)
RT_DEBUG_DIO_EXT_TMR_CBK,
#endif /* USE_RT_DEBUG_DIO_EXT_TMR_CBK */
#if (USE_RT_DEBUG_RCO_CLBR_TMR_CBK == 1)
RT_DEBUG_RCO_CLBR_TMR_CBK,
#endif /* USE_RT_DEBUG_RCO_CLBR_TMR_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_ADV_CBK == 1)
RT_DEBUG_ADV_EXT_MNGR_ADV_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_ADV_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_CBK == 1)
RT_DEBUG_ADV_EXT_MNGR_SCN_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK == 1)
RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_ERR_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK == 1)
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK == 1)
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_ERR_CBK */
#if (USE_RT_DEBUG_BIG_ADV_CBK == 1)
RT_DEBUG_BIG_ADV_CBK,
#endif /* USE_RT_DEBUG_BIG_ADV_CBK */
#if (USE_RT_DEBUG_BIG_ADV_ERR_CBK == 1)
RT_DEBUG_BIG_ADV_ERR_CBK,
#endif /* USE_RT_DEBUG_BIG_ADV_ERR_CBK */
#if (USE_RT_DEBUG_BIG_SYNC_CBK == 1)
RT_DEBUG_BIG_SYNC_CBK,
#endif /* USE_RT_DEBUG_BIG_SYNC_CBK */
#if (USE_RT_DEBUG_BIG_SYNC_ERR_CBK == 1)
RT_DEBUG_BIG_SYNC_ERR_CBK,
#endif /* USE_RT_DEBUG_BIG_SYNC_ERR_CBK */
#if (USE_RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK == 1)
RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK,
#endif /* USE_RT_DEBUG_ISO_CIS_PKT_TRNSM_RECEIVED_CBK */
#if (USE_RT_DEBUG_ISO_CIG_ERR_CBK == 1)
RT_DEBUG_ISO_CIG_ERR_CBK,
#endif /* USE_RT_DEBUG_ISO_CIG_ERR_CBK */
#if (USE_RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK == 1)
RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK,
#endif /* USE_RT_DEBUG_CONN_PKT_TRNSM_RECEIVED_CBK */
#if (USE_RT_DEBUG_PRDC_CLBR_EXTRL_CBK == 1)
RT_DEBUG_PRDC_CLBR_EXTRL_CBK,
#endif /* USE_RT_DEBUG_PRDC_CLBR_EXTRL_CBK */
#if (USE_RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK == 1)
RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK,
#endif /* USE_RT_DEBUG_PTR_PRDC_ADV_SYNC_CBK */
#if (USE_RT_DEBUG_NCONN_SCN_CBK == 1)
RT_DEBUG_NCONN_SCN_CBK,
#endif /* USE_RT_DEBUG_NCONN_SCN_CBK */
#if (USE_RT_DEBUG_NCONN_ADV_CBK == 1)
RT_DEBUG_NCONN_ADV_CBK,
#endif /* USE_RT_DEBUG_NCONN_ADV_CBK */
#if (USE_RT_DEBUG_NCONN_INIT_CBK == 1)
RT_DEBUG_NCONN_INIT_CBK,
#endif /* USE_RT_DEBUG_NCONN_INIT_CBK */
#if (USE_RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK == 1)
RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK,
#endif /* USE_RT_DEBUG_ANT_RADIO_CMPLT_EVNT_CBK */
#if (USE_RT_DEBUG_ANT_STACK_EVNT_CBK == 1)
RT_DEBUG_ANT_STACK_EVNT_CBK,
#endif /* USE_RT_DEBUG_ANT_STACK_EVNT_CBK */
#if (USE_RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK == 1)
RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK,
#endif /* USE_RT_DEBUG_ADV_EXT_PROCESS_TMOUT_EVNT_CBK */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT == 1)
RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_DUR_EVNT */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT == 1)
RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_SCN_PERIODIC_EVNT */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT == 1)
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_TMOUT_EVNT */
#if (USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT == 1)
RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT,
#endif /* USE_RT_DEBUG_ADV_EXT_MNGR_PRDC_SCN_CNCEL_EVNT */
#if (USE_RT_DEBUG_BIS_MNGR_BIG_TERM_CBK == 1)
RT_DEBUG_BIS_MNGR_BIG_TERM_CBK,
#endif /* USE_RT_DEBUG_BIS_MNGR_BIG_TERM_CBK */
#if (USE_RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK == 1)
RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK,
#endif /* USE_RT_DEBUG_BIS_MNGR_SYNC_TMOUT_CBK */
#if (USE_RT_DEBUG_ISOAL_MNGR_SDU_GEN == 1)
RT_DEBUG_ISOAL_MNGR_SDU_GEN,
#endif /* USE_RT_DEBUG_ISOAL_MNGR_SDU_GEN */
#if (USE_RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK == 1)
RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK,
#endif /* USE_RT_DEBUG_ISO_MNGR_CIS_PROCESS_EVNT_CBK */
#if (USE_RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK == 1)
RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK,
#endif /* USE_RT_DEBUG_CONN_MNGR_PROCESS_EVNT_CLBK */
#if (USE_RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK == 1)
RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK,
#endif /* USE_RT_DEBUG_CONN_MNGR_UPDT_CONN_PARAM_CBK */
#if (USE_RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT == 1)
RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT,
#endif /* USE_RT_DEBUG_EVNT_SCHDLR_HW_EVNT_CMPLT */
#if (USE_RT_DEBUG_HCI_EVENT_HNDLR == 1)
RT_DEBUG_HCI_EVENT_HNDLR,
#endif /* USE_RT_DEBUG_HCI_EVENT_HNDLR */
#if (USE_RT_DEBUG_MLME_TMRS_CBK == 1)
RT_DEBUG_MLME_TMRS_CBK,
#endif /* USE_RT_DEBUG_MLME_TMRS_CBK */
#if (USE_RT_DEBUG_DIRECT_TX_EVNT_CBK == 1)
RT_DEBUG_DIRECT_TX_EVNT_CBK,
#endif /* USE_RT_DEBUG_DIRECT_TX_EVNT_CBK */
#if (USE_RT_DEBUG_INDIRECT_PKT_TOUR_CBK == 1)
RT_DEBUG_INDIRECT_PKT_TOUR_CBK,
#endif /* USE_RT_DEBUG_INDIRECT_PKT_TOUR_CBK */
#if (USE_RT_DEBUG_RADIO_CSMA_TMR == 1)
RT_DEBUG_RADIO_CSMA_TMR,
#endif /* USE_RT_DEBUG_RADIO_CSMA_TMR */
#if (USE_RT_DEBUG_RAL_SM_DONE_EVNT_CBK == 1)
RT_DEBUG_RAL_SM_DONE_EVNT_CBK,
#endif /* USE_RT_DEBUG_RAL_SM_DONE_EVNT_CBK */
#if (USE_RT_DEBUG_ED_TMR_HNDL == 1)
RT_DEBUG_ED_TMR_HNDL,
#endif /* USE_RT_DEBUG_ED_TMR_HNDL */
#if (USE_RT_DEBUG_OS_TMR_EVNT_CBK == 1)
RT_DEBUG_OS_TMR_EVNT_CBK,
#endif /* USE_RT_DEBUG_OS_TMR_EVNT_CBK */
#if (USE_RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME == 1)
RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME,
#endif /* USE_RT_DEBUG_PROFILE_MARKER_PHY_WAKEUP_TIME */
#if (USE_RT_DEBUG_PROFILE_END_DRIFT_TIME == 1)
RT_DEBUG_PROFILE_END_DRIFT_TIME,
#endif /* USE_RT_DEBUG_PROFILE_END_DRIFT_TIME */
#if (USE_RT_DEBUG_PROC_RADIO_RCV == 1)
RT_DEBUG_PROC_RADIO_RCV,
#endif /* USE_RT_DEBUG_PROC_RADIO_RCV */
#if (USE_RT_DEBUG_EVNT_TIME_UPDT == 1)
RT_DEBUG_EVNT_TIME_UPDT,
#endif /* USE_RT_DEBUG_EVNT_TIME_UPDT */
#if (USE_RT_DEBUG_MAC_RECEIVE_DONE == 1)
RT_DEBUG_MAC_RECEIVE_DONE,
#endif /* USE_RT_DEBUG_MAC_RECEIVE_DONE */
#if (USE_RT_DEBUG_MAC_TX_DONE == 1)
RT_DEBUG_MAC_TX_DONE,
#endif /* USE_RT_DEBUG_MAC_TX_DONE */
#if (USE_RT_DEBUG_RADIO_APPLY_CSMA == 1)
RT_DEBUG_RADIO_APPLY_CSMA,
#endif /* USE_RT_DEBUG_RADIO_APPLY_CSMA */
#if (USE_RT_DEBUG_RADIO_TRANSMIT == 1)
RT_DEBUG_RADIO_TRANSMIT,
#endif /* USE_RT_DEBUG_RADIO_TRANSMIT */
#if (USE_RT_DEBUG_PROC_RADIO_TX == 1)
RT_DEBUG_PROC_RADIO_TX,
#endif /* USE_RT_DEBUG_PROC_RADIO_TX */
#if (USE_RT_DEBUG_RAL_TX_DONE == 1)
RT_DEBUG_RAL_TX_DONE,
#endif /* USE_RT_DEBUG_RAL_TX_DONE */
#if (USE_RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT == 1)
RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT,
#endif /* USE_RT_DEBUG_RAL_TX_DONE_INCREMENT_BACKOFF_COUNT */
#if (USE_RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT == 1)
RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT,
#endif /* USE_RT_DEBUG_RAL_TX_DONE_RST_BACKOFF_COUNT */
#if (USE_RT_DEBUG_RAL_CONTINUE_RX == 1)
RT_DEBUG_RAL_CONTINUE_RX,
#endif /* USE_RT_DEBUG_RAL_CONTINUE_RX */
#if (USE_RT_DEBUG_RAL_PERFORM_CCA == 1)
RT_DEBUG_RAL_PERFORM_CCA,
#endif /* USE_RT_DEBUG_RAL_PERFORM_CCA */
#if (USE_RT_DEBUG_RAL_ENABLE_TRANSMITTER == 1)
RT_DEBUG_RAL_ENABLE_TRANSMITTER,
#endif /* USE_RT_DEBUG_RAL_ENABLE_TRANSMITTER */
#if (USE_RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2 == 1)
RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2,
#endif /* USE_RT_DEBUG_LLHWC_GET_CH_IDX_ALGO_2 */
#if (USE_RT_DEBUG_BACK_FROM_DEEP_SLEEP == 1)
RT_DEBUG_BACK_FROM_DEEP_SLEEP,
#endif /* USE_RT_DEBUG_BACK_FROM_DEEP_SLEEP */
#include "app_debug_signal_def.h"
RT_DEBUG_SIGNALS_TOTAL_NUM
} rt_debug_signal_t;
#endif /* CFG_RT_DEBUG_GPIO_MODULE */
#ifdef __cplusplus
}
#endif
#endif /* DEBUG_SIGNALS_H */

View File

@@ -0,0 +1,114 @@
/**
******************************************************************************
* @file serial_cmd_interpreter.c
* @author MCD Application Team
* @brief Source file for the serial commands interpreter module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "log_module.h"
#include "app_conf.h"
#include "stm32_adv_trace.h"
#include "serial_cmd_interpreter.h"
/* Private includes -----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/
#define RX_BUFF_SIZE (256U)
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint8_t RxBuffer[RX_BUFF_SIZE];
static uint16_t indexRxBuffer = 0;
/* Global variables ----------------------------------------------------------*/
/* Private functions prototypes ----------------------------------------------*/
static void UART_Rx_Callback(uint8_t *PData, uint16_t Size, uint8_t Error);
/* External variables --------------------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
void Serial_CMD_Interpreter_Init(void)
{
/* Init Communication reception. Need that Log/Traces are activated */
UTIL_ADV_TRACE_StartRxProcess(UART_Rx_Callback);
}
__weak void Serial_CMD_Interpreter_CmdExecute( uint8_t * pRxBuffer, uint16_t iRxBufferSize )
{
/* NOTE : This function should not be modified, when the callback is needed,
the enter_standby_notification could be implemented in the user file
*/
/*
This user function is in charge of interpreting the received data.
Here is an example of how to use them.
In this simple case, we'll generate a SW IT on GPIO14 if the received data is a string "TEST".
Add the following code into the user code section :
// Extended line handler on which we will generate the IT
EXTI_HandleTypeDef exti_handle;
// Check RxBuffer's content to know if we're matching our case
if( strcmp( (char const*)pRxBuffer, "TEST" ) == 0 )
{
LOG_INFO_APP("TEST has been received in Uart_Cmd_Execute.\n");
exti_handle.Line = EXTI_LINE_14;
HAL_EXTI_GenerateSWI(&exti_handle);
}
*/
}
/* Private functions definition ----------------------------------------------*/
static void UART_Rx_Callback( uint8_t * pData, uint16_t Size, uint8_t Error )
{
/* Filling buffer and wait for '\r' charactere to execute actions */
if ( indexRxBuffer < RX_BUFF_SIZE )
{
if ( *pData == '\r' )
{
Serial_CMD_Interpreter_CmdExecute( RxBuffer, indexRxBuffer );
/* Clear receive buffer and character counter*/
indexRxBuffer = 0;
memset( &RxBuffer[0], 0, RX_BUFF_SIZE );
}
else
{
if ( ( * pData == '\n' ) && ( indexRxBuffer == 0 ) )
{
/* discard this first charactere if it's a delimiter */
}
else
{
RxBuffer[indexRxBuffer++] = *pData;
}
}
}
else
{
indexRxBuffer = 0;
memset(&RxBuffer[0], 0, RX_BUFF_SIZE);
}
return;
}

View File

@@ -0,0 +1,47 @@
/**
******************************************************************************
* @file serial_cmd_interpreter.h
* @author MCD Application Team
* @brief Header file for the serial commands interpreter module.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef SERIAL_CMD_INTERPRETER_H
#define SERIAL_CMD_INTERPRETER_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Private includes ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
void Serial_CMD_Interpreter_Init(void);
void Serial_CMD_Interpreter_CmdExecute( uint8_t * pRxBuffer, uint16_t iRxBufferSize );
/* Private defines -----------------------------------------------------------*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SERIAL_CMD_INTERPRETER_H */

View File

@@ -0,0 +1,892 @@
/**
******************************************************************************
* @file adc_ctrl.c
* @author MCD Application Team
* @brief Source file for ADC controller module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Utilities */
#include "utilities_common.h"
/* Real time trace for debug */
#include "RTDebug.h"
/* Own header files */
#include "adc_ctrl.h"
#include "adc_ctrl_conf.h"
/* LL ADC header */
#include "stm32wbaxx_ll_adc.h"
/* Private defines -----------------------------------------------------------*/
/**
* @brief Initial value define for configuration tracking number
*/
#define ADCCTRL_NO_CONFIG (uint32_t)(0x00000000u)
/**
* @brief Init variable out of expected ADC conversion data range
*/
#define VAR_CONVERTED_DATA_INIT_VALUE_12B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B) + 1)
#define VAR_CONVERTED_DATA_INIT_VALUE_10B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_10B) + 1)
#define VAR_CONVERTED_DATA_INIT_VALUE_8B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_8B) + 1)
#define VAR_CONVERTED_DATA_INIT_VALUE_6B (__LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_6B) + 1)
/**
* @brief Internal temperature sensor, parameter V30 (unit: mV).
*
* @details Refer to device datasheet for min/typ/max values.
*
*/
#define TEMPSENSOR_TYP_CAL1_V (( int32_t) 760)
/**
* @brief Internal temperature sensor, parameter Avg_Slope (unit: uV/DegCelsius).
*
* @details Refer to device datasheet for min/typ/max values.
*
*/
#define TEMPSENSOR_TYP_AVGSLOPE (( int32_t) 2500)
/* Definitions of environment analog values */
/**
* @brief Value of analog reference voltage (Vref+), connected to analog voltage
*
* @details supply Vdda (unit: mV).
*
*/
#define VDDA_APPLI (3300UL)
/* Private typedef -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/**
* @brief ADC IP Client list
*/
static uint32_t ClientList;
/**
* @brief Tracker of the current applied configuration
*/
static uint32_t CurrentConfig = ADCCTRL_NO_CONFIG;
/**
* @brief Higher registered handle ID
*/
static uint32_t MaxRegisteredId = ADCCTRL_NO_CONFIG;
/**
* @brief Handle of the ADC
*/
static ADC_TypeDef * p_ADCHandle = ADCCTRL_HWADDR;
/* Global variables ----------------------------------------------------------*/
/* Error Handler */
extern void Error_Handler(void);
/* Private function prototypes -----------------------------------------------*/
/**
* @brief Activate ADC.
* Activation order is as follow:
* - Enable ADC peripharal clock
* - Enable ADC internal voltage regulator
* - Enable ADC
* @param None
* @retval None
*/
static inline void AdcActivate (void);
/**
* @brief Deactivate ADC IP.
* Deactivation order is as follow:
* - Disable ADC
* - Disable ADC internal voltage regulator
* - Disable ADC peripharal clock
* @param None
* @retval None
*/
static inline void AdcDeactivate (void);
/**
* @brief Configure ADC IP.
* @param p_Handle: Handle to work with
* @retval State of the configuration
*/
static inline ADCCTRL_Cmd_Status_t AdcConfigure (const ADCCTRL_Handle_t * const p_Handle);
/**
* @brief Read the raw value
* @param p_Handle: Handle to work with
* @return Raw value
*/
static inline uint16_t AdcReadRaw (const ADCCTRL_Handle_t * const p_Handle);
/**
* @brief Perform ADC group regular conversion start, poll for conversion
* completion.
* (ADCCTRL_HWADDR instance: ADC).
* @note This function does not perform ADC group regular conversion stop:
* intended to be used with ADC in single mode, trigger SW start
* (only 1 ADC conversion done at each trigger, no conversion stop
* needed).
* In case of continuous mode or conversion trigger set to
* external trigger, ADC group regular conversion stop must be added.
* @param None
* @retval None
*/
static inline void ConversionStartPoll_ADC_GrpRegular (void);
/* Functions Definition ------------------------------------------------------*/
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_Init (void)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
CurrentConfig = ADCCTRL_NO_CONFIG;
p_ADCHandle = ADCCTRL_HWADDR;
/* Reset ADC Client list */
ClientList = 0x00u;
/* Deactivate the ADC */
AdcDeactivate();
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RegisterHandle (ADCCTRL_Handle_t * const p_Handle)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
if (NULL == p_Handle)
{
error = ADCCTRL_ERROR_NULL_POINTER;
}
else if (ADCCTRL_HANDLE_REG == p_Handle->State)
{
error = ADCCTRL_HANDLE_ALREADY_REGISTERED;
}
else
{
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
/* Update the maximum registered handle */
MaxRegisteredId = MaxRegisteredId + 1u;
/* Update the handle UUID */
p_Handle->Uid = MaxRegisteredId;
/* Set handle as initialized */
p_Handle->State = ADCCTRL_HANDLE_REG;
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestIpState (const ADCCTRL_Handle_t * const p_Handle,
const ADCCTRL_Ip_State_t State)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
UTILS_ENTER_CRITICAL_SECTION();
if (ADC_OFF == State)
{
ClientList &= (~(1U << p_Handle->Uid));
error = ADCCTRL_OK;
}
else if (ADC_ON == State)
{
ClientList |= (1U << p_Handle->Uid);
error = ADCCTRL_OK;
}
else
{
error = ADCCTRL_ERROR_STATE;
}
if (0x00u == ClientList)
{
/* Disable ADC as there is no request anymore */
AdcDeactivate();
}
else
{
/* Enable ADC as there at least one request */
AdcActivate();
}
UTILS_EXIT_CRITICAL_SECTION();
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestRawValue (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == p_ReadValue))
{
error = ADCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
{
error = ADCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = ADCCTRL_HANDLE_NOT_VALID;
}
/* Check ADC state */
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
{
error = ADCCTRL_ERROR_STATE;
}
else
{
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
/* Is the current config IS NOT the same as the one requested ? */
if (CurrentConfig != p_Handle->Uid)
{
/* Configure the ADC before use */
error = AdcConfigure (p_Handle);
/* Enable ADC */
LL_ADC_Enable(p_ADCHandle);
}
if (ADCCTRL_OK == error)
{
/* Return the read value */
*p_ReadValue = AdcReadRaw (p_Handle);
}
else
{
error = ADCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestTemperature (const ADCCTRL_Handle_t * const p_Handle,
int16_t * const p_ReadValue)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
/* Variables for ADC conversion data */
__IO uint16_t uhADCxConvertedData = 0x00;
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == p_ReadValue))
{
error = ADCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
{
error = ADCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = ADCCTRL_HANDLE_NOT_VALID;
}
/* Check ADC state */
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
{
error = ADCCTRL_ERROR_STATE;
}
else
{
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
/* Is the current config IS NOT the same as the one requested ? */
if (CurrentConfig != p_Handle->Uid)
{
/* Configure the ADC before use */
error = AdcConfigure (p_Handle);
/* Enable ADC */
LL_ADC_Enable(p_ADCHandle);
}
if (ADCCTRL_OK == error)
{
/* Return the read value */
uhADCxConvertedData = AdcReadRaw (p_Handle);
/* Computation of ADC conversions raw data to physical values */
/* using LL ADC driver helper macro. */
if(*TEMPSENSOR_CAL1_ADDR == *TEMPSENSOR_CAL2_ADDR)
{
/* Case of samples not calibrated in production */
*p_ReadValue = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS (TEMPSENSOR_TYP_AVGSLOPE,
TEMPSENSOR_TYP_CAL1_V,
TEMPSENSOR_CAL1_TEMP,
VDDA_APPLI,
uhADCxConvertedData,
p_Handle->InitConf.ConvParams.Resolution);
}
else
{
/* Case of samples calibrated in production */
*p_ReadValue = __LL_ADC_CALC_TEMPERATURE (VDDA_APPLI,
uhADCxConvertedData,
p_Handle->InitConf.ConvParams.Resolution);
}
}
else
{
error = ADCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestCoreVoltage (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
/* Variables for ADC conversion data */
__IO uint16_t uhADCxConvertedData = 0x00;
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == p_ReadValue))
{
error = ADCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
{
error = ADCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = ADCCTRL_HANDLE_NOT_VALID;
}
/* Check ADC state */
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
{
error = ADCCTRL_ERROR_STATE;
}
else
{
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
/* Is the current config IS NOT the same as the one requested ? */
if (CurrentConfig != p_Handle->Uid)
{
/* Configure the ADC before use */
error = AdcConfigure (p_Handle);
/* Enable ADC */
LL_ADC_Enable(p_ADCHandle);
}
if (ADCCTRL_OK == error)
{
/* Return the read value */
uhADCxConvertedData = AdcReadRaw (p_Handle);
/* Computation of ADC conversions raw data to physical values */
/* using LL ADC driver helper macro. */
*p_ReadValue = __LL_ADC_CALC_DATA_TO_VOLTAGE (VDDA_APPLI,
uhADCxConvertedData,
p_Handle->InitConf.ConvParams.Resolution);
}
else
{
error = ADCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_RequestRefVoltage (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_UNKNOWN;
/* Variables for ADC conversion data */
__IO uint16_t uhADCxConvertedData = 0x00;
SYSTEM_DEBUG_SIGNAL_SET(ADC_TEMPERATURE_ACQUISITION);
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == p_ReadValue))
{
error = ADCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (ADCCTRL_HANDLE_NOT_REG == p_Handle->State)
{
error = ADCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(ADCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = ADCCTRL_HANDLE_NOT_VALID;
}
/* Check ADC state */
else if (0x00u == (ClientList & (1U << p_Handle->Uid)))
{
error = ADCCTRL_ERROR_STATE;
}
else
{
/* Try to take the ADC mutex */
error = ADCCTRL_MutexTake ();
if (ADCCTRL_OK == error)
{
/* Is the current config IS NOT the same as the one requested ? */
if (CurrentConfig != p_Handle->Uid)
{
/* Configure the ADC before use */
error = AdcConfigure (p_Handle);
/* Enable ADC */
LL_ADC_Enable(p_ADCHandle);
}
if (ADCCTRL_OK == error)
{
/* Return the read value */
uhADCxConvertedData = AdcReadRaw (p_Handle);
/* Computation of ADC conversions raw data to physical values */
/* using LL ADC driver helper macro. */
*p_ReadValue = __LL_ADC_CALC_VREFANALOG_VOLTAGE (uhADCxConvertedData,
p_Handle->InitConf.ConvParams.Resolution);
}
else
{
error = ADCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
ADCCTRL_MutexRelease ();
}
}
return error;
}
/* Private function Definition -----------------------------------------------*/
void AdcActivate (void)
{
__IO uint32_t backup_setting_adc_dma_transfer = 0U;
SYSTEM_DEBUG_SIGNAL_SET(ADC_ACTIVATION);
UTILS_ENTER_CRITICAL_SECTION();
/*## Operation on ADC hierarchical scope: ADC instance #####################*/
/* Note: Hardware constraint (refer to description of the functions */
/* below): */
/* On this STM32 series, setting of these features is conditioned to */
/* ADC state: */
/* ADC must be disabled. */
/* Note: In this example, all these checks are not necessary but are */
/* implemented anyway to show the best practice usages */
/* corresponding to reference manual procedure. */
/* Software can be optimized by removing some of these checks, if */
/* they are not relevant considering previous settings and actions */
/* in user application. */
if (LL_ADC_IsEnabled(p_ADCHandle) == 0)
{
/* Select clock source */
ADCTCTRL_SET_CLOCK_SOURCE ();
/* Peripheral clock enable */
ADCCTRL_ENABLE_CLOCK ();
/* Enable ADC internal voltage regulator */
LL_ADC_EnableInternalRegulator(p_ADCHandle);
/* Waiting for ADC internal voltage regulator stabilization. */
while(LL_ADC_IsInternalRegulatorEnabled(p_ADCHandle) == 0);
/* Disable ADC DMA transfer request during calibration */
/* Note: Specificity of this STM32 series: Calibration factor is */
/* available in data register and also transferred by DMA. */
/* To not insert ADC calibration factor among ADC conversion data */
/* in DMA destination address, DMA transfer must be disabled during */
/* calibration. */
backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p_ADCHandle);
LL_ADC_REG_SetDMATransfer(p_ADCHandle, LL_ADC_REG_DMA_TRANSFER_NONE);
/* Run ADC self calibration */
LL_ADC_StartCalibration(p_ADCHandle);
/* Poll for ADC effectively calibrated */
while (LL_ADC_IsCalibrationOnGoing(p_ADCHandle) != 0);
/* Restore ADC DMA transfer request after calibration */
LL_ADC_REG_SetDMATransfer(p_ADCHandle, backup_setting_adc_dma_transfer);
/* Delay required between ADC end of calibration and ADC enable */
/* LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES --> 2 cycles */
__asm("mov r0, r0");
__asm("mov r0, r0");
/* Enable ADC */
LL_ADC_Enable(p_ADCHandle);
/* Poll for ADC ready to convert */
while (LL_ADC_IsActiveFlag_ADRDY(p_ADCHandle) == 0);
/* Note: ADC flag ADRDY is not cleared here to be able to check ADC */
/* status afterwards. */
/* This flag should be cleared at ADC Deactivation, before a new */
/* ADC activation, using function "LL_ADC_ClearFlag_ADRDY()". */
}
/*## Operation on ADC hierarchical scope: ADC group regular ################*/
/* Note: No operation on ADC group regular performed here. */
/* ADC group regular conversions to be performed after this function */
/* using function: */
/* "LL_ADC_REG_StartConversion();" */
/*## Operation on ADC hierarchical scope: ADC group injected ###############*/
/* Note: Feature not available on this STM32 series */
UTILS_EXIT_CRITICAL_SECTION();
SYSTEM_DEBUG_SIGNAL_RESET(ADC_ACTIVATION);
}
void AdcDeactivate (void)
{
SYSTEM_DEBUG_SIGNAL_SET(ADC_DEACTIVATION);
UTILS_ENTER_CRITICAL_SECTION();
if(LL_ADC_IsEnabled(p_ADCHandle))
{
/* Disable ADC */
LL_ADC_Disable(p_ADCHandle);
/* Clear flag ADC ready */
LL_ADC_ClearFlag_ADRDY(p_ADCHandle);
/* Wait until ADC_CR_ADEN bit is reset before turning off ADC internal regulator */
while(LL_ADC_IsEnabled(p_ADCHandle) == 1UL);
/* Wait until ADC_CR_ADSTP bit is reset before turning off ADC internal regulator */
while(LL_ADC_REG_IsStopConversionOngoing(p_ADCHandle) == 1U);
/* Disable ADC internal voltage regulator */
LL_ADC_DisableInternalRegulator(p_ADCHandle);
while(LL_ADC_IsInternalRegulatorEnabled(p_ADCHandle) == 1U);
/* Peripharal clock disable */
ADCCTRL_DISABLE_CLOCK ();
}
UTILS_EXIT_CRITICAL_SECTION();
SYSTEM_DEBUG_SIGNAL_RESET(ADC_DEACTIVATION);
}
ADCCTRL_Cmd_Status_t AdcConfigure (const ADCCTRL_Handle_t * const p_Handle)
{
ADCCTRL_Cmd_Status_t error = ADCCTRL_OK;
__IO uint32_t backup_setting_adc_dma_transfer = 0U;
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
/* DeInit the ADC module */
if (SUCCESS != LL_ADC_DeInit (p_ADCHandle))
{
error = ADCCTRL_NOK;
}
else
{
/* Restart a calibration */
/* Disable ADC DMA transfer request during calibration */
/* Note: Specificity of this STM32 series: Calibration factor is */
/* available in data register and also transferred by DMA. */
/* To not insert ADC calibration factor among ADC conversion data */
/* in DMA destination address, DMA transfer must be disabled during */
/* calibration. */
backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(p_ADCHandle);
LL_ADC_REG_SetDMATransfer(p_ADCHandle, LL_ADC_REG_DMA_TRANSFER_NONE);
/* Run ADC self calibration */
LL_ADC_StartCalibration(p_ADCHandle);
/* Poll for ADC effectively calibrated */
while (LL_ADC_IsCalibrationOnGoing(p_ADCHandle) != 0);
/* Restore ADC DMA transfer request after calibration */
LL_ADC_REG_SetDMATransfer(p_ADCHandle, backup_setting_adc_dma_transfer);
/* Delay required between ADC end of calibration and ADC enable */
/* LL_ADC_DELAY_CALIB_ENABLE_ADC_CYCLES --> 2 cycles */
__asm("mov r0, r0");
__asm("mov r0, r0");
}
/* All OK ? */
if (ADCCTRL_OK == error)
{
/* Update init and configuration parameters with requested values */
ADC_InitStruct.Resolution = p_Handle->InitConf.ConvParams.Resolution;
ADC_InitStruct.DataAlignment = p_Handle->InitConf.ConvParams.DataAlign;
ADC_REG_InitStruct.TriggerSource = p_Handle->InitConf.ConvParams.TriggerStart;
ADC_REG_InitStruct.SequencerLength = p_Handle->InitConf.SeqParams.Length;
ADC_REG_InitStruct.SequencerDiscont = p_Handle->InitConf.SeqParams.DiscMode;
ADC_REG_InitStruct.ContinuousMode = p_Handle->InitConf.ConvParams.ConversionMode;
ADC_REG_InitStruct.DMATransfer = p_Handle->InitConf.ConvParams.DmaTransfer;
ADC_REG_InitStruct.Overrun = p_Handle->InitConf.ConvParams.Overrun;
/* Configure Regular Channel - Only for internal channels */
if (LL_ADC_CHANNEL_VREFINT == p_Handle->ChannelConf.Channel)
{
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
LL_ADC_PATH_INTERNAL_VREFINT);
}
else if (LL_ADC_CHANNEL_TEMPSENSOR == p_Handle->ChannelConf.Channel)
{
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
LL_ADC_PATH_INTERNAL_TEMPSENSOR);
}
else
{
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(p_ADCHandle),
LL_ADC_PATH_INTERNAL_NONE);
}
/* Set trigger frequency */
LL_ADC_SetTriggerFrequencyMode(p_ADCHandle,
p_Handle->InitConf.ConvParams.TriggerFrequencyMode);
/* Apply the requested ADC configuration - Init part */
if (SUCCESS != LL_ADC_Init(p_ADCHandle,
&ADC_InitStruct))
{
error = ADCCTRL_NOK;
}
else
{
/* Set Sequencer if configurable */
LL_ADC_REG_SetSequencerConfigurable(p_ADCHandle,
p_Handle->InitConf.SeqParams.Setup);
/* Apply the requested ADC configuration - Register init part */
if (SUCCESS != LL_ADC_REG_Init(p_ADCHandle,
&ADC_REG_InitStruct))
{
error = ADCCTRL_NOK;
}
else
{
/* Set Low power characteristics */
LL_ADC_SetLPModeAutoPowerOff(p_ADCHandle,
p_Handle->InitConf.LowPowerParams.AutoPowerOff);
LL_ADC_SetLPModeAutonomousDPD(p_ADCHandle,
p_Handle->InitConf.LowPowerParams.AutonomousDPD);
/* Set Sampling time for channels */
LL_ADC_SetSamplingTimeCommonChannels(p_ADCHandle,
LL_ADC_SAMPLINGTIME_COMMON_1,
p_Handle->InitConf.ConvParams.SamplingTimeCommon1);
LL_ADC_SetSamplingTimeCommonChannels(p_ADCHandle,
LL_ADC_SAMPLINGTIME_COMMON_2,
p_Handle->InitConf.ConvParams.SamplingTimeCommon2);
/* Configure the channel */
LL_ADC_REG_SetSequencerRanks(p_ADCHandle,
p_Handle->ChannelConf.Rank,
p_Handle->ChannelConf.Channel);
LL_ADC_SetChannelSamplingTime(p_ADCHandle,
p_Handle->ChannelConf.Channel,
p_Handle->ChannelConf.SamplingTime);
/* Update the current configuration */
CurrentConfig = p_Handle->Uid;
}
}
}
return error;
}
uint16_t AdcReadRaw (const ADCCTRL_Handle_t * const p_Handle)
{
/* Variables for ADC conversion data */
__IO uint16_t uhADCxConvertedData = 0x00;
/* Perform ADC group regular conversion start, poll for conversion */
/* completion. */
ConversionStartPoll_ADC_GrpRegular ();
/* Retrieve ADC conversion data */
switch (p_Handle->InitConf.ConvParams.Resolution)
{
case LL_ADC_RESOLUTION_12B:
{
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_12B;
uhADCxConvertedData = LL_ADC_REG_ReadConversionData12(p_ADCHandle);
break;
}
case LL_ADC_RESOLUTION_10B:
{
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_10B;
uhADCxConvertedData = LL_ADC_REG_ReadConversionData10(p_ADCHandle);
break;
}
case LL_ADC_RESOLUTION_8B:
{
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_8B;
uhADCxConvertedData = LL_ADC_REG_ReadConversionData8(p_ADCHandle);
break;
}
case LL_ADC_RESOLUTION_6B:
{
uhADCxConvertedData = VAR_CONVERTED_DATA_INIT_VALUE_6B;
uhADCxConvertedData = LL_ADC_REG_ReadConversionData6(p_ADCHandle);
break;
}
default:
{
/* Do nothing */
break;
}
}
return uhADCxConvertedData;
}
void ConversionStartPoll_ADC_GrpRegular (void)
{
/* Start ADC group regular conversion */
/* Note: Hardware constraint (refer to description of the function */
/* below): */
/* On this STM32 series, setting of this feature is conditioned to */
/* ADC state: */
/* ADC must be enabled without conversion on going on group regular, */
/* without ADC disable command on going. */
/* Note: In this example, all these checks are not necessary but are */
/* implemented anyway to show the best practice usages */
/* corresponding to reference manual procedure. */
/* Software can be optimized by removing some of these checks, if */
/* they are not relevant considering previous settings and actions */
/* in user application. */
if ((LL_ADC_IsEnabled(p_ADCHandle) == 1) &&
(LL_ADC_IsDisableOngoing(p_ADCHandle) == 0) &&
(LL_ADC_REG_IsConversionOngoing(p_ADCHandle) == 0) )
{
LL_ADC_REG_StartConversion(p_ADCHandle);
}
else
{
/* Error: ADC conversion start could not be performed */
Error_Handler();
}
while (LL_ADC_IsActiveFlag_EOC(p_ADCHandle) == 0);
/* Clear flag ADC group regular end of unitary conversion */
/* Note: This action is not needed here, because flag ADC group regular */
/* end of unitary conversion is cleared automatically when */
/* software reads conversion data from ADC data register. */
/* Nevertheless, this action is done anyway to show how to clear */
/* this flag, needed if conversion data is not always read */
/* or if group injected end of unitary conversion is used (for */
/* devices with group injected available). */
LL_ADC_ClearFlag_EOC(p_ADCHandle);
}
/* Weak function Definition --------------------------------------------------*/
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_MutexTake (void)
{
return ADCCTRL_OK;
}
__WEAK ADCCTRL_Cmd_Status_t ADCCTRL_MutexRelease (void)
{
return ADCCTRL_OK;
}

View File

@@ -0,0 +1,276 @@
/**
******************************************************************************
* @file adc_ctrl.h
* @author MCD Application Team
* @brief Header for ADC client manager module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef ADC_CTRL_H
#define ADC_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Utilities */
#include "utilities_common.h"
/* Exported defines ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/**
* @brief ADC command status codes
*/
typedef enum ADCCTRL_Cmd_Status
{
ADCCTRL_OK,
ADCCTRL_NOK,
ADCCTRL_BUSY,
ADCCTRL_HANDLE_ALREADY_REGISTERED,
ADCCTRL_HANDLE_NOT_REGISTERED,
ADCCTRL_HANDLE_NOT_VALID,
ADCCTRL_ERROR_NULL_POINTER,
ADCCTRL_ERROR_CONFIG,
ADCCTRL_ERROR_STATE,
ADCCTRL_UNKNOWN,
} ADCCTRL_Cmd_Status_t;
/**
* @brief ADC IP state
*/
typedef enum ADCCTRL_Ip_State
{
ADC_OFF,
ADC_ON
} ADCCTRL_Ip_State_t;
/**
* @brief ADC handle states
*/
typedef enum ADCCTRL_HandleState
{
ADCCTRL_HANDLE_NOT_REG,
ADCCTRL_HANDLE_REG,
} ADCCTRL_HandleState_t;
/**
* @brief ADC Init configuration structure - Conversion parameters
*/
typedef struct ADCCTRL_ConvParameters
{
uint32_t TriggerFrequencyMode; /*!< Set ADC Trigger frequency mode.
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_FREQ */
uint32_t Resolution; /*!< Configure the ADC resolution.
This parameter can be a value of @ref ADC_LL_EC_RESOLUTION */
uint32_t DataAlign; /*!< Specify ADC data alignment in conversion data register (right or left).
This parameter can be a value of @ref ADC_LL_EC_DATA_ALIGN */
uint32_t TriggerStart; /*!< Select the source used to trigger ADC conversion
start.
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_SOURCE.*/
uint32_t TriggerEdge; /*!< Select the Edge used for trigger.
This parameter can be a value of @ref ADC_LL_EC_REG_TRIGGER_EDGE.*/
uint32_t ConversionMode; /*!< Configure the conversion mode of ADC.
This parameter can be a value of @ref ADC_LL_EC_REG_CONTINUOUS_MODE */
uint32_t DmaTransfer; /*!< DMA transfer of ADC conversion data.
This parameter can be a value of @ref ADC_LL_EC_REG_DMA_TRANSFER */
uint32_t Overrun; /*!< Select the behavior in case of overrun: data overwritten or preserved (default).
This parameter can be a value of @ref ADC_LL_EC_REG_OVR_DATA_BEHAVIOR. */
uint32_t SamplingTimeCommon1; /*!< Set sampling time common to a group of channels.
This parameter can be a value of @ref ADC_LL_EC_CHANNEL_SAMPLINGTIME */
uint32_t SamplingTimeCommon2; /*!< Set sampling time common to a group of channels, second common setting possible.
This parameter can be a value of @ref ADC_LL_EC_CHANNEL_SAMPLINGTIME */
}ADCCTRL_ConvParameters_t;
/**
* @brief ADC Init configuration structure - Sequencer parameters
*/
typedef struct ADCCTRL_SeqParameters
{
uint32_t Setup; /*!< Set ADC sequencer configuration flexibility.
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_MODE */
uint32_t Length; /*!< Set ADC sequencer scan length.
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_SCAN_LENGTH */
uint32_t DiscMode; /*!< Set ADC sequencer discontinuous mode.
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_DISCONT_MODE */
}ADCCTRL_SeqParameters_t;
/**
* @brief ADC Init configuration structure - Low power parameters
*/
typedef struct ADCCTRL_LowPowerParameters
{
FunctionalState AutoPowerOff; /*!< Enable or Disable ADC Auto Power OFF mode.
This parameter can be set to ENABLE or DISABLE */
uint32_t AutonomousDPD; /*!< Enable or Disable ADC Autonomous Deep Power Down Mode.
This parameter can be a value of @ref ADC_LL_EC_AUTONOMOUS_DEEP_POWER_DOWN_MODE */
}ADCCTRL_LowPowerParameters_t;
/**
* @brief ADC Init configuration structure
*/
typedef struct ADCCTRL_InitConfig
{
ADCCTRL_ConvParameters_t ConvParams;
ADCCTRL_SeqParameters_t SeqParams;
ADCCTRL_LowPowerParameters_t LowPowerParams;
} ADCCTRL_InitConfig_t;
/**
* @brief ADC Channel configuration structure
*/
typedef struct ADCCTRL_ChannelConfig
{
uint32_t Channel; /*!< Specify the channel to configure into ADC regular group.
This parameter can be a value of @ref ADC_LL_EC_CHANNEL */
uint32_t Rank; /*!< Add or remove the channel from ADC regular group sequencer and specify its
conversion rank.
This parameter can be a value of @ref ADC_LL_EC_REG_SEQ_RANKS */
uint32_t SamplingTime; /*!< Sampling time value to be set for the selected channel.
This parameter can be a value of @ref ADC_LL_EC_SAMPLINGTIME_COMMON */
} ADCCTRL_ChannelConfig_t;
/**
* @brief ADC handle typedef
*/
typedef struct ADCCTRL_Handle
{
uint32_t Uid; /* Id of the Handle instance */
ADCCTRL_HandleState_t State; /* State of the ADC Controller handle */
ADCCTRL_InitConfig_t InitConf; /* Init configuration of the ADC */
ADCCTRL_ChannelConfig_t ChannelConf; /* Channel configuration of the ADC */
} ADCCTRL_Handle_t;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Initialize the adc controller
*
* @retval State of the initialization
*/
ADCCTRL_Cmd_Status_t ADCCTRL_Init(void);
/**
* @brief Register a ADC handle
*
* @param p_Handle: Handle to register
*
* @return State of the handle initialization
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RegisterHandle (ADCCTRL_Handle_t * const p_Handle);
/**
* @brief Request a specific state for the ADC IP - Either On or Off
*
* @param p_Handle: ADC handle
* @param State: Requested state to apply
*
* @return State of the operation
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RequestIpState (const ADCCTRL_Handle_t * const p_Handle,
const ADCCTRL_Ip_State_t State);
/**
* @brief Read raw value of the ADC
*
* @param p_Handle: ADC handle
* @param p_ReadValue: Raw ADC value
*
* @retval Operation state
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RequestRawValue (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue);
/**
* @brief Read temperature from ADC temperature sensor
*
* @details The returned value is actual temperature sensor value
*
* @param p_Handle: ADC handle
* @param p_ReadValue: Temperature measurement
*
* @retval Operation state
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RequestTemperature (const ADCCTRL_Handle_t * const p_Handle,
int16_t * const p_ReadValue);
/**
* @brief Read Voltage from ADC
*
* @details The returned value is actual Voltage value in mVolts
*
* @param p_Handle: ADC handle
* @param p_ReadValue: Core Voltage measurement
*
* @retval Operation state
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RequestCoreVoltage (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue);
/**
* @brief Read reference Voltage from ADC
*
* @details The returned value is actual reference Voltage value in mVolts
*
* @param p_Handle: ADC handle
* @param p_ReadValue: Reference Voltage measurement
*
* @retval Operation state
*/
ADCCTRL_Cmd_Status_t ADCCTRL_RequestRefVoltage (const ADCCTRL_Handle_t * const p_Handle,
uint16_t * const p_ReadValue);
/* Exported functions to be implemented by the user ------------------------- */
/**
* @brief Take ownership on the ADC mutex
*
* @details This function shall be implemented by the user
*
* @return Status of the command
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_OK
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_NOK
*/
extern ADCCTRL_Cmd_Status_t ADCCTRL_MutexTake (void);
/**
* @brief Release ownership on the ADC mutex
*
* @details This function shall be implemented by the user
*
* @return Status of the command
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_OK
* @retval ADCCTRL_Cmd_Status_t::ADCCTRL_NOK
*/
extern ADCCTRL_Cmd_Status_t ADCCTRL_MutexRelease (void);
#ifdef __cplusplus
}
#endif
#endif /* ADC_CTRL_H */

View File

@@ -0,0 +1,123 @@
/**
******************************************************************************
* @file app_sys.c
* @author MCD Application Team
* @brief Application system for STM32WPAN Middleware.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "app_sys.h"
#include "app_conf.h"
#include "timer_if.h"
#include "stm32_lpm.h"
#include "ll_intf.h"
#include "ll_sys.h"
#if (UTIL_LPM_LEGACY_ENABLED == 0)
#include "stm32_lpm_if.h"
#endif
#if MAC
#include "ral.h"
#endif
/* External functions --------------------------------------------------------*/
extern uint32_t llhwc_cmn_is_dp_slp_enabled(void);
/* External variables --------------------------------------------------------*/
/* Private variables --------------------------------------------------------*/
static uint32_t wakeup_offset = RADIO_DEEPSLEEP_WAKEUP_TIME_US;
/* Functions Definition ------------------------------------------------------*/
/**
*
*/
#if SUPPORT_BLE
void APP_SYS_BLE_EnterDeepSleep(void)
{
ble_stat_t cmd_status;
uint32_t radio_remaining_time = 0;
if (ll_sys_dp_slp_get_state() == LL_SYS_DP_SLP_DISABLED)
{
/* Enable radio to retrieve next radio activity */
/* Getting next radio event time if any */
cmd_status = ll_intf_le_get_remaining_time_for_next_event(&radio_remaining_time);
UNUSED(cmd_status);
assert_param(cmd_status == SUCCESS);
if (radio_remaining_time == LL_DP_SLP_NO_WAKEUP)
{
/* No next radio event scheduled */
(void)ll_sys_dp_slp_enter(LL_DP_SLP_NO_WAKEUP);
}
else if (radio_remaining_time > wakeup_offset)
{
/* No event in a "near" futur */
(void)ll_sys_dp_slp_enter(radio_remaining_time - wakeup_offset);
}
else
{
#if (UTIL_LPM_LEGACY_ENABLED == 1)
UTIL_LPM_SetOffMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_DISABLE);
#else /* (UTIL_LPM_LEGACY_ENABLED == 1) */
#if (CFG_LPM_STOP1_SUPPORTED == 1)
UTIL_LPM_SetMaxMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_STOP1_MODE);
#else /* (CFG_LPM_STOP1_SUPPORTED == 1) */
UTIL_LPM_SetMaxMode(1U << CFG_LPM_LL_DEEPSLEEP, UTIL_LPM_SLEEP_MODE);
#endif /* (CFG_LPM_STOP1_SUPPORTED == 1) */
#endif /* (UTIL_LPM_LEGACY_ENABLED == 1) */
}
}
}
#else /* SUPPORT_BLE */
/**
*
*/
void APP_SYS_LPM_EnterLowPowerMode(void)
{
ral_instance_t radio_instance;
uint8_t channel;
uint64_t next_radio_evt;
/* Ensure there are no radio events (implement bsp function like bsp_is_radio_idle() ) */
ral_event_state_enum_t radio_state = ral_get_current_event_state( &radio_instance, &channel );
LL_UNUSED(radio_instance);
LL_UNUSED(channel);
if (radio_state != RAL_IDLE)
{
return;
}
next_radio_evt = os_timer_get_earliest_time();
if ( llhwc_cmn_is_dp_slp_enabled() == 0 )
{
if ( next_radio_evt > wakeup_offset )
{
/* No event in a "near" futur */
ll_sys_dp_slp_enter( next_radio_evt - wakeup_offset );
}
}
}
#endif /* SUPPORT_BLE */
void APP_SYS_SetWakeupOffset(uint32_t wakeup_offset_us)
{
wakeup_offset = wakeup_offset_us;
}

View File

@@ -0,0 +1,307 @@
/**
******************************************************************************
* @file crc_ctrl.c
* @author MCD Application Team
* @brief Source for CRC client controller module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Utilities */
#include "utilities_common.h"
/* Own header files */
#include "crc_ctrl.h"
#include "crc_ctrl_conf.h"
/* HAL CRC header */
#include "stm32wbaxx_hal_crc.h"
/* Private defines -----------------------------------------------------------*/
/**
* @brief Initial value define for configuration tracking number
*
*/
#define CRCCTRL_NO_CONFIG (uint32_t)(0x00000000u)
/* Private typedef -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/**
* @brief Tracker of the current applied configuration
*/
static uint32_t CurrentConfig = CRCCTRL_NO_CONFIG;
/**
* @brief Higher registered handle ID
*/
static uint32_t MaxRegisteredId = CRCCTRL_NO_CONFIG;
/**
* @brief Handle of the HAL CRC
*/
static CRC_HandleTypeDef CRCHandle =
{
.Instance = CRCCTRL_HWADDR,
};
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/**
* @brief Configure CRC IP
* @param p_Handle: CRC handle
* @retval State of the configuration
*/
static inline HAL_StatusTypeDef CrcConfigure (CRCCTRL_Handle_t * const p_Handle);
/* Functions Definition ------------------------------------------------------*/
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Init (void)
{
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
/* Try to take the CRC mutex */
error = CRCCTRL_MutexTake ();
if (CRCCTRL_OK == error)
{
CurrentConfig = CRCCTRL_NO_CONFIG;
CRCHandle.State = HAL_CRC_STATE_RESET;
CRCHandle.Instance = CRCCTRL_HWADDR;
/* Release the mutex */
CRCCTRL_MutexRelease ();
}
return error;
}
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_RegisterHandle (CRCCTRL_Handle_t * const p_Handle)
{
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
if (NULL == p_Handle)
{
error = CRCCTRL_ERROR_NULL_POINTER;
}
else if (HANDLE_REG == p_Handle->State)
{
error = CRCCTRL_HANDLE_ALREADY_REGISTERED;
}
else
{
/* Try to take the CRC mutex */
error = CRCCTRL_MutexTake ();
if (CRCCTRL_OK == error)
{
/* Update the maximum registered handle */
MaxRegisteredId = MaxRegisteredId + 1u;
/* Update the handle UUID */
p_Handle->Uid = MaxRegisteredId;
/* Init the previous value */
p_Handle->PreviousComputedValue = p_Handle->Configuration.InitValue;
/* Set handle as initialized */
p_Handle->State = HANDLE_REG;
/* Release the mutex */
CRCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Calculate (CRCCTRL_Handle_t * const p_Handle,
uint32_t a_Payload[],
const uint32_t PayloadSize,
uint32_t * const p_ConmputedValue)
{
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
HAL_StatusTypeDef eReturn = HAL_OK;
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == a_Payload) || (NULL == p_ConmputedValue))
{
error = CRCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (HANDLE_NOT_REG == p_Handle->State)
{
error = CRCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(CRCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = CRCCTRL_HANDLE_NOT_VALID;
}
else
{
/* Try to take the CRC mutex */
error = CRCCTRL_MutexTake ();
if (CRCCTRL_OK == error)
{
/* Is the current config IS NOT the same as the one requested ? */
if (CurrentConfig != p_Handle->Uid)
{
/* Configure the CRC before use */
eReturn = CrcConfigure (p_Handle);
}
if (eReturn == HAL_OK)
{
*p_ConmputedValue = HAL_CRC_Calculate (&CRCHandle, a_Payload, PayloadSize);
/* Update the handle with the computed value */
p_Handle->PreviousComputedValue = *p_ConmputedValue;
}
else
{
error = CRCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
CRCCTRL_MutexRelease ();
}
}
return error;
}
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_Accumulate (CRCCTRL_Handle_t * const p_Handle,
uint32_t a_Payload[],
const uint32_t PayloadSize,
uint32_t * const p_ConmputedValue)
{
CRCCTRL_Cmd_Status_t error = CRCCTRL_UNKNOWN;
/* Null pointer for handle or payload */
if ((NULL == p_Handle) || (NULL == a_Payload) || (NULL == p_ConmputedValue))
{
error = CRCCTRL_ERROR_NULL_POINTER;
}
/* Handle not init */
else if (HANDLE_NOT_REG == p_Handle->State)
{
error = CRCCTRL_HANDLE_NOT_REGISTERED;
}
/* Handle not in the range */
else if ((MaxRegisteredId < p_Handle->Uid) ||
(CRCCTRL_NO_CONFIG >= p_Handle->Uid))
{
error = CRCCTRL_HANDLE_NOT_VALID;
}
else
{
/* Try to take the CRC mutex */
error = CRCCTRL_MutexTake ();
if (CRCCTRL_OK == error)
{
/* Check if the config has to change */
if (CurrentConfig == p_Handle->Uid)
{
*p_ConmputedValue = HAL_CRC_Accumulate (&CRCHandle,
a_Payload,
PayloadSize);
/* Update the handle with the computed value */
p_Handle->PreviousComputedValue = *p_ConmputedValue;
}
/* Configure the CRC before use */
else if (HAL_OK == CrcConfigure (p_Handle))
{
/* Before starting the accumulation, the init register shall be written with the previous value */
CRCHandle.Instance->INIT = p_Handle->PreviousComputedValue;
*p_ConmputedValue = HAL_CRC_Calculate (&CRCHandle,
a_Payload,
PayloadSize);
/* Update the handle with the computed value */
p_Handle->PreviousComputedValue = *p_ConmputedValue;
}
else
{
error = CRCCTRL_ERROR_CONFIG;
}
/* Release the mutex */
CRCCTRL_MutexRelease ();
}
}
return error;
}
/* Private function Definition -----------------------------------------------*/
HAL_StatusTypeDef CrcConfigure (CRCCTRL_Handle_t * const p_Handle)
{
HAL_StatusTypeDef error = HAL_OK;
/* No need to DeInit if the CRC if it is not yet initialized */
if (HAL_CRC_STATE_RESET != CRCHandle.State)
{
/* DeInit the CRC module */
error = HAL_CRC_DeInit(&CRCHandle);
}
/* All OK ? */
if (HAL_OK == error)
{
/* Fulfill the configuration part */
CRCHandle.Init.CRCLength = p_Handle->Configuration.CRCLength;
CRCHandle.Init.DefaultInitValueUse = p_Handle->Configuration.DefaultInitValueUse;
CRCHandle.Init.DefaultPolynomialUse = p_Handle->Configuration.DefaultPolynomialUse;
CRCHandle.Init.GeneratingPolynomial = p_Handle->Configuration.GeneratingPolynomial;
CRCHandle.Init.InitValue = p_Handle->Configuration.InitValue;
CRCHandle.Init.InputDataInversionMode = p_Handle->Configuration.InputDataInversionMode;
CRCHandle.Init.OutputDataInversionMode = p_Handle->Configuration.OutputDataInversionMode;
CRCHandle.InputDataFormat = p_Handle->Configuration.InputDataFormat;
/* Apply the requested CRC configuration */
error = HAL_CRC_Init(&CRCHandle);
if (HAL_OK == error)
{
/* Update the current configuration */
CurrentConfig = p_Handle->Uid;
}
else
{
/* There must be an issue with configuration, clean the configuration */
memset ((void *)(&CRCHandle.Init),
0x00,
sizeof (CRC_InitTypeDef));
CRCHandle.InputDataFormat = 0x00u;
}
}
return error;
}
/* Weak function Definition --------------------------------------------------*/
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_MutexTake (void)
{
return CRCCTRL_OK;
}
__WEAK CRCCTRL_Cmd_Status_t CRCCTRL_MutexRelease (void)
{
return CRCCTRL_OK;
}

View File

@@ -0,0 +1,214 @@
/**
******************************************************************************
* @file crc_ctrl.h
* @author MCD Application Team
* @brief Header for CRC client manager module
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef CRC_CTRL_H
#define CRC_CTRL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Utilities */
#include "utilities_common.h"
/* HAL CRC header */
#include "stm32wbaxx_hal_crc.h"
/* Exported defines ----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/**
* @brief CRC command status codes
*/
typedef enum CRCCTRL_Cmd_Status
{
CRCCTRL_OK,
CRCCTRL_NOK,
CRCCTRL_BUSY,
CRCCTRL_HANDLE_ALREADY_REGISTERED,
CRCCTRL_HANDLE_NOT_REGISTERED,
CRCCTRL_HANDLE_NOT_VALID,
CRCCTRL_ERROR_NULL_POINTER,
CRCCTRL_ERROR_CONFIG,
CRCCTRL_UNKNOWN,
} CRCCTRL_Cmd_Status_t;
/**
* @brief CRC command status codes
*/
typedef enum CRCCTRL_HandleState
{
HANDLE_NOT_REG,
HANDLE_REG,
} CRCCTRL_HandleState_t;
/**
* @brief CRC configuration structure
*
*/
typedef struct CRCCTRL_Config
{
uint8_t DefaultPolynomialUse; /*!< This parameter is a value of @ref CRC_Default_Polynomial and indicates if default polynomial is used.
If set to DEFAULT_POLYNOMIAL_ENABLE, resort to default
X^32 + X^26 + X^23 + X^22 + X^16 + X^12 + X^11 + X^10 +X^8 + X^7 + X^5 +
X^4 + X^2+ X +1.
In that case, there is no need to set GeneratingPolynomial field.
If otherwise set to DEFAULT_POLYNOMIAL_DISABLE, GeneratingPolynomial and
CRCLength fields must be set. */
uint8_t DefaultInitValueUse; /*!< This parameter is a value of @ref CRC_Default_InitValue_Use and indicates if default init value is used.
If set to DEFAULT_INIT_VALUE_ENABLE, resort to default
0xFFFFFFFF value. In that case, there is no need to set InitValue field. If
otherwise set to DEFAULT_INIT_VALUE_DISABLE, InitValue field must be set. */
uint32_t GeneratingPolynomial; /*!< Set CRC generating polynomial as a 7, 8, 16 or 32-bit long value for a polynomial degree
respectively equal to 7, 8, 16 or 32. This field is written in normal,
representation e.g., for a polynomial of degree 7, X^7 + X^6 + X^5 + X^2 + 1
is written 0x65. No need to specify it if DefaultPolynomialUse is set to
DEFAULT_POLYNOMIAL_ENABLE. */
uint32_t CRCLength; /*!< This parameter is a value of @ref CRC_Polynomial_Sizes and indicates CRC length.
Value can be either one of
@arg @ref CRC_POLYLENGTH_32B (32-bit CRC),
@arg @ref CRC_POLYLENGTH_16B (16-bit CRC),
@arg @ref CRC_POLYLENGTH_8B (8-bit CRC),
@arg @ref CRC_POLYLENGTH_7B (7-bit CRC). */
uint32_t InitValue; /*!< Init value to initiate CRC computation. No need to specify it if DefaultInitValueUse
is set to DEFAULT_INIT_VALUE_ENABLE. */
uint32_t InputDataInversionMode; /*!< This parameter is a value of @ref CRCEx_Input_Data_Inversion and specifies input data inversion mode.
Can be either one of the following values
@arg @ref CRC_INPUTDATA_INVERSION_NONE no input data inversion
@arg @ref CRC_INPUTDATA_INVERSION_BYTE byte-wise inversion, 0x1A2B3C4D
becomes 0x58D43CB2
@arg @ref CRC_INPUTDATA_INVERSION_HALFWORD halfword-wise inversion,
0x1A2B3C4D becomes 0xD458B23C
@arg @ref CRC_INPUTDATA_INVERSION_WORD word-wise inversion, 0x1A2B3C4D
becomes 0xB23CD458 */
uint32_t OutputDataInversionMode; /*!< This parameter is a value of @ref CRCEx_Output_Data_Inversion and specifies output data (i.e. CRC) inversion mode.
Can be either
@arg @ref CRC_OUTPUTDATA_INVERSION_DISABLE no CRC inversion,
@arg @ref CRC_OUTPUTDATA_INVERSION_ENABLE CRC 0x11223344 is converted
into 0x22CC4488 */
uint32_t InputDataFormat; /*!< This parameter is a value of @ref CRC_Input_Buffer_Format and specifies input data format.
Can be either
@arg @ref CRC_INPUTDATA_FORMAT_BYTES input data is a stream of bytes
(8-bit data)
@arg @ref CRC_INPUTDATA_FORMAT_HALFWORDS input data is a stream of
half-words (16-bit data)
@arg @ref CRC_INPUTDATA_FORMAT_WORDS input data is a stream of words
(32-bit data)
Note that constant CRC_INPUT_FORMAT_UNDEFINED is defined but an initialization
error must occur if InputBufferFormat is not one of the three values listed
above */
} CRCCTRL_Config_t;
typedef struct CRCCTRL_Handle
{
uint32_t Uid; /* Id of the Handle instance */
uint32_t PreviousComputedValue; /* Previous CRC computed value for Accumulate purposes */
CRCCTRL_HandleState_t State; /* State of the CRC Controller handle */
CRCCTRL_Config_t Configuration; /* Configuration of the CRC */
} CRCCTRL_Handle_t;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Init the CRC Ctrl variables
*
* @return State of the handle initialization
*/
CRCCTRL_Cmd_Status_t CRCCTRL_Init (void);
/**
* @brief Register a CRC handle
*
* @param p_Handle: Handle to register
*
* @return State of the handle registration
*/
CRCCTRL_Cmd_Status_t CRCCTRL_RegisterHandle (CRCCTRL_Handle_t * const p_Handle);
/**
* @brief Compute the CRC of the given payload
*
* @param p_Handle: CRC handle
* @param a_Payload: Address of the first payload element
* @param PayloadSize: Size of the payload to compute the CRC
* @param p_ComputedValue: Computed CRC (returned value LSBs for CRC shorter than 32 bits)
*
* @return State of the operation
*/
CRCCTRL_Cmd_Status_t CRCCTRL_Calculate (CRCCTRL_Handle_t * const p_Handle,
uint32_t a_Payload[],
const uint32_t PayloadSize,
uint32_t * const p_ConmputedValue);
/**
* @brief Keep computing the CRC of a given payload
*
* @details Computation starts with the previous computed CRC as initialization value.
*
* @details The CRCCTRL_Calculate shall be used before any call of this API.
*
* @param p_Handle: Address of the first payload element
* @param a_Payload: Address of the first payload element
* @param PayloadSize: Size of the payload to compute the CRC
* @param p_ComputedValue: Computed CRC (returned value LSBs for CRC shorter than 32 bits)
*
* @return State of the operation
*/
CRCCTRL_Cmd_Status_t CRCCTRL_Accumulate (CRCCTRL_Handle_t * const p_Handle,
uint32_t a_Payload[],
const uint32_t PayloadSize,
uint32_t * const p_ConmputedValue);
/* Exported functions to be implemented by the user ------------------------- */
/**
* @brief Take ownership on the CRC mutex
*
* @details This function shall be implemented by the user
*
* @return Status of the command
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_OK
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_NOK
*/
extern CRCCTRL_Cmd_Status_t CRCCTRL_MutexTake (void);
/**
* @brief Release ownership on the CRC mutex
*
* @details This function shall be implemented by the user
*
* @return Status of the command
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_OK
* @retval CRCCTRL_Cmd_Status_t::CRCCTRL_NOK
*/
extern CRCCTRL_Cmd_Status_t CRCCTRL_MutexRelease (void);
#ifdef __cplusplus
}
#endif
#endif /* CRC_CTRL_H */

View File

@@ -0,0 +1,101 @@
/**
******************************************************************************
* @file dbg_trace.h
* @author MCD Application Team
* @brief Header for dbg_trace.c
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef DBG_TRACE_H
#define DBG_TRACE_H
#ifdef __cplusplus
extern "C"
{
#endif
/* Exported types ------------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
#if ( ( CFG_DEBUG_TRACE_FULL != 0 ) || ( CFG_DEBUG_TRACE_LIGHT != 0 ) )
#define PRINT_LOG_BUFF_DBG(...) DbgTraceBuffer(__VA_ARGS__)
#if ( CFG_DEBUG_TRACE_FULL != 0 )
#define PRINT_MESG_DBG(...) do{printf("\r\n [%s][%s][%d] ", DbgTraceGetFileName(__FILE__),__FUNCTION__,__LINE__);printf(__VA_ARGS__);}while(0);
#else
#define PRINT_MESG_DBG printf
#endif
#else
#define PRINT_LOG_BUFF_DBG(...)
#define PRINT_MESG_DBG(...)
#endif
#define PRINT_NO_MESG(...)
/* Exported functions ------------------------------------------------------- */
/**
* @brief Request the user to initialize the peripheral to output traces
*
* @param None
* @retval None
*/
extern void DbgOutputInit( void );
/**
* @brief Request the user to sent the traces on the output peripheral
*
* @param p_data: Address of the buffer to be sent
* @param size: Size of the data to be sent
* @param cb: Function to be called when the data has been sent
* @retval None
*/
extern void DbgOutputTraces( uint8_t *p_data, uint16_t size, void (*cb)(void) );
/**
* @brief DbgTraceInit Initialize Logging feature.
*
* @param: None
* @retval: None
*/
void DbgTraceInit( void );
/**********************************************************************************************************************/
/** This function outputs into the log the buffer (in hex) and the provided format string and arguments.
***********************************************************************************************************************
*
* @param pBuffer Buffer to be output into the logs.
* @param u32Length Length of the buffer, in bytes.
* @param strFormat The format string in printf() style.
* @param ... Arguments of the format string.
*
**********************************************************************************************************************/
void DbgTraceBuffer( const void *pBuffer , uint32_t u32Length , const char *strFormat , ... );
const char *DbgTraceGetFileName( const char *fullpath );
/**
* @brief Override the standard lib function to redirect printf to USART.
* @param handle output handle (STDIO, STDERR...)
* @param buf buffer to write
* @param bufsize buffer size
* @retval Number of elements written
*/
size_t DbgTraceWrite(int handle, const unsigned char * buf, size_t bufSize);
#ifdef __cplusplus
}
#endif
#endif /* DBG_TRACE_H */

View File

@@ -0,0 +1,98 @@
/**
******************************************************************************
* @file otp.c
* @author MCD HW Board & MCD Application Team
* @brief Source file for One Time Programmable (OTP) area
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "otp.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
HAL_StatusTypeDef OTP_Read(uint8_t index, OTP_Data_s** otp_ptr)
{
*otp_ptr = (OTP_Data_s*) (FLASH_OTP_BASE + FLASH_OTP_SIZE - 16);
while ( (*otp_ptr)->index != index && (*otp_ptr) != (OTP_Data_s*) FLASH_OTP_BASE)
{
(*otp_ptr) -= 1;
}
if ((*otp_ptr)->index != index)
{
return HAL_ERROR;
}
return HAL_OK;
}
HAL_StatusTypeDef OTP_Write(uint8_t* additional_data, uint8_t* bd_address, uint8_t hsetune, uint8_t index)
{
HAL_StatusTypeDef err = HAL_ERROR;
OTP_Data_s otp_data;
int i;
/* Fill OTP_Data_s structure */
for (i = 0; i < sizeof(otp_data.additional_data); i++)
{
otp_data.additional_data[i] = additional_data[i];
}
for (i = 0; i < sizeof(otp_data.bd_address); i++)
{
otp_data.bd_address[i] = bd_address[i];
}
otp_data.hsetune = hsetune;
otp_data.index = index;
/* Find free space */
uint32_t free_address = FLASH_OTP_BASE;
while ( ( *(uint64_t*)(free_address) != 0xFFFFFFFFFFFFFFFFUL ) &&
( *(uint64_t*)(free_address + 8) != 0xFFFFFFFFFFFFFFFFUL ) &&
( (free_address + 16) != FLASH_OTP_BASE + FLASH_OTP_SIZE ) )
{
free_address += 16;
}
if ( ( *(uint64_t*)(free_address) == 0xFFFFFFFFFFFFFFFFUL ) &&
( *(uint64_t*)(free_address + 8) == 0xFFFFFFFFFFFFFFFFUL ) )
{
/* Store OTP structure in OTP area */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); /* Clear all Flash flags before write operation*/
err = HAL_FLASH_Unlock();
err |= HAL_FLASH_Program(FLASH_NSCR1_PG, free_address, (uint32_t) &otp_data);
err |= HAL_FLASH_Lock();
}
return err;
}
/* Private functions ---------------------------------------------------------*/

View File

@@ -0,0 +1,87 @@
/**
******************************************************************************
* @file otp.h
* @author MCD HW Board & MCD Application Team
* @brief Header file for One Time Programmable (OTP) area
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef OTP_H
#define OTP_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32wbaxx_hal.h"
#include "cmsis_compiler.h"
/* Exported types ------------------------------------------------------------*/
/*
--------------------------------------------------------------------------------
|LSB MSB|
--------------------------------------------------------------------------------
| additional_data 8-bytes | bd_address 6 bytes | hsetune 1 byte | index 1 byte |
--------------------------------------------------------------------------------
*/
typedef __PACKED_STRUCT
{
uint8_t additional_data[8]; /*!< 64 bits of data to fill OTP slot Ex: MB184510 */
uint8_t bd_address[6]; /*!< Bluetooth Device Address*/
uint8_t hsetune; /*!< Load capacitance to be applied on HSE pad */
uint8_t index; /*!< Structure index */
} OTP_Data_s;
/* Exported constants --------------------------------------------------------*/
#define DEFAULT_OTP_IDX 0
/* Exported macro ------------------------------------------------------------*/
/* Exported variables ------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
/**
* * @brief Minimal code to use the OTP_Read function:
*
OTP_Data_s* otp_ptr = NULL;
if (OTP_Read(DEFAULT_OTP_IDX, &otp_ptr) != HAL_OK) {
return HAL_ERROR;
}
uint64_t bd_addr = (uint64_t) otp_ptr->bd_address[0] |
(uint64_t) otp_ptr->bd_address[1] << 8 |
(uint64_t) otp_ptr->bd_address[2] << 16 |
(uint64_t) otp_ptr->bd_address[3] << 24 |
(uint64_t) otp_ptr->bd_address[4] << 32 |
(uint64_t) otp_ptr->bd_address[5] << 40 ;
uint8_t hsetune = otp_ptr->hsetune;
uint8_t index = otp_ptr->index;
*/
HAL_StatusTypeDef OTP_Read(uint8_t index, OTP_Data_s** data);
/**
* @brief Write OTP
*/
HAL_StatusTypeDef OTP_Write(uint8_t* additional_data, uint8_t* bd_address, uint8_t hsetune, uint8_t index);
#ifdef __cplusplus
}
#endif
#endif /* OTP_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,286 @@
/**
******************************************************************************
* @file scm.h
* @author MCD Application Team
* @brief Header for scm.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef SCM_H
#define SCM_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#if (CFG_SCM_SUPPORTED == 1)
#include "stm32wbaxx_hal.h"
#include "stm32wbaxx_ll_pwr.h"
#include "stm32wbaxx_ll_rcc.h"
#include "stm32wbaxx_ll_tim.h"
/* Exported types ------------------------------------------------------------*/
typedef enum {
NO_CLOCK_CONFIG = 0,
HSE_16MHZ,
HSE_32MHZ,
SYS_PLL,
} scm_clockconfig_t;
typedef enum {
LP,
RUN,
HSE16,
HSE32,
PLL,
} scm_ws_lp_t;
typedef enum {
HSEPRE_DISABLE = 0,
HSEPRE_ENABLE
} scm_hse_hsepre_t;
typedef enum {
SCM_USER_APP,
SCM_USER_LL_FW,
SCM_USER_LL_HW_RCO_CLBR,
TOTAL_CLIENT_NUM, /* To be at the end of the enum */
} scm_user_id_t;
typedef enum {
NO_PLL,
PLL_INTEGER_MODE,
PLL_FRACTIONAL_MODE,
} scm_pll_mode_t;
typedef enum {
SCM_RADIO_NOT_ACTIVE = 0,
SCM_RADIO_ACTIVE,
} scm_radio_state_t;
typedef struct {
uint8_t are_pll_params_initialized;
scm_pll_mode_t pll_mode;
uint32_t PLLM;
uint32_t PLLN;
uint32_t PLLP;
uint32_t PLLQ;
uint32_t PLLR;
uint32_t PLLFractional;
uint32_t AHB5_PLL1_CLKDivider;
} scm_pll_config_t;
typedef struct{
scm_clockconfig_t targeted_clock_freq;
uint32_t flash_ws_cfg;
uint32_t sram_ws_cfg;
scm_pll_config_t pll;
} scm_system_clock_t;
/* Exported constants --------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief System Clock Manager init code
* @param None
* @retval None
*/
void scm_init(void);
/**
* @brief Setup the system clock source in usable configuration for Connectivity use cases.
* Called at startup or out of low power modes.
* @param None
* @retval None
*/
void scm_setup(void);
/**
* @brief Configure the PLL mode and parameters before PLL selection as system clock.
* @param p_pll_config PLL coniguration to apply
* @retval None
* @note scm_pll_setconfig to be called before PLL activation (PLL set as system core clock)
*/
void scm_pll_setconfig(const scm_pll_config_t *p_pll_config);
/**
* @brief Restore system clock configuration when moving out of standby.
* @param None
* @retval None
*/
void scm_standbyexit(void);
/**
* @brief Return the state of the Radio.
* @param None
* @retval radio_state
*/
scm_radio_state_t isRadioActive(void);
/**
* @brief Configure the PLL for switching fractional parameters on the fly.
* @param pll_frac Up to date fractional configuration.
* @retval None
* @note A PLL update is requested only when the system clock is
* running on the PLL with a different configuration that the
* one required.
*/
void scm_pll_fractional_update(uint32_t pll_frac);
/**
* @brief Set the HSE clock to the requested frequency.
* @param user_id This parameter can be one of the following:
* @arg SCM_USER_APP
* @arg SCM_USER_LL_FW
* @param sysclockconfig This parameter can be one of the following:
* @arg HSE_16MHZ
* @arg HSE_32MHZ
* @arg SYS_PLL
* @retval None
*/
void scm_setsystemclock (scm_user_id_t user_id, scm_clockconfig_t sysclockconfig);
/**
* @brief Called each time the PLL is ready
* @param None
* @retval None
* @note This function is defined as weak in SCM module.
* Can be overridden by user.
*/
void scm_pllready(void);
/**
* @brief Configure the Flash and SRAMs wait cycle (when required for system clock source change)
* @param ws_lp_config: This parameter can be one of the following:
* @arg LP
* @arg RUN
* @arg HSE16
* @arg HSE32
* @arg PLL
* @retval None
*/
void scm_setwaitstates(const scm_ws_lp_t ws_lp_config);
/**
* @brief Notify the state of the Radio
* @param radio_state: This parameter can be one of the following:
* @arg SCM_RADIO_ACTIVE
* @arg SCM_RADIO_NOT_ACTIVE
* @retval None
*/
void scm_notifyradiostate(const scm_radio_state_t radio_state);
/**
* @brief SCM HSERDY interrupt handler.
* Switch system clock on HSE.
* @param None
* @retval None
*/
void scm_hserdy_isr(void);
/**
* @brief SCM PLLRDY interrupt handler.
* Switch system clock on PLL.
* @param None
* @retval None
*/
void scm_pllrdy_isr(void);
/* SCM HSE BEGIN */
/**
* @brief Getter for SW HSERDY flag
*/
uint8_t SCM_HSE_Get_SW_HSERDY(void);
/**
* @brief Setter for SW HSERDY flag
*/
void SCM_HSE_Set_SW_HSERDY(void);
/**
* @brief Clean of SW HSERDY flag
*/
void SCM_HSE_Clear_SW_HSERDY(void);
/**
* @brief Polling function to wait until HSE is ready
*/
void SCM_HSE_WaitUntilReady(void);
/**
* @brief Start the HSE stabilization timer
*/
void SCM_HSE_StartStabilizationTimer(void);
/**
* @brief Stop the HSE stabilization timer
*/
void SCM_HSE_StopStabilizationTimer(void);
/**
* @brief HSE stabilization timer interrupt handler
*/
void SCM_HSE_SW_HSERDY_isr(void);
/* SCM HSE END */
/* Exported functions - To be implemented by the user ------------------------- */
/**
* @brief SCM HSI clock enable
* @details A weak version is implemented in the module sources.
* @details It can be overridden by user.
* @param None
* @retval None
*/
extern void SCM_HSI_CLK_ON(void);
/**
* @brief SCM HSI clock may be disabled when this function is called
* @details A weak version is implemented in the module sources.
* @details It can be overridden by user.
* @param None
* @retval None
*/
extern void SCM_HSI_CLK_OFF(void);
/* SCM HSE BEGIN */
/**
* @brief Entry hook for HSI switch
*/
extern void SCM_HSI_SwithSystemClock_Entry(void);
/**
* @brief Exit hook for HSI switch
*/
extern void SCM_HSI_SwithSystemClock_Exit(void);
/* SCM HSE END */
#else /* CFG_SCM_SUPPORTED */
/* Unused empty functions */
void scm_hserdy_isr(void);
void scm_pllrdy_isr(void);
#endif /* CFG_SCM_SUPPORTED */
#ifdef __cplusplus
}
#endif
#endif /* SCM_H */

View File

@@ -0,0 +1,199 @@
/**
******************************************************************************
* @file stm_list.c
* @author MCD Application Team
* @brief TCircular Linked List Implementation.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/******************************************************************************
* Include Files
******************************************************************************/
#include "stm_list.h"
/******************************************************************************
* Function Definitions
******************************************************************************/
void LST_init_head (tListNode * listHead)
{
listHead->next = listHead;
listHead->prev = listHead;
}
uint8_t LST_is_empty (tListNode * listHead)
{
uint32_t primask_bit;
uint8_t return_value;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
if(listHead->next == listHead)
{
return_value = TRUE;
}
else
{
return_value = FALSE;
}
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
return return_value;
}
void LST_insert_head (tListNode * listHead, tListNode * node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
node->next = listHead->next;
node->prev = listHead;
listHead->next = node;
(node->next)->prev = node;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_insert_tail (tListNode * listHead, tListNode * node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
node->next = listHead;
node->prev = listHead->prev;
listHead->prev = node;
(node->prev)->next = node;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_remove_node (tListNode * node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
(node->prev)->next = node->next;
(node->next)->prev = node->prev;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_remove_head (tListNode * listHead, tListNode ** node )
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
*node = listHead->next;
LST_remove_node (listHead->next);
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_remove_tail (tListNode * listHead, tListNode ** node )
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
*node = listHead->prev;
LST_remove_node (listHead->prev);
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_insert_node_after (tListNode * node, tListNode * ref_node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
node->next = ref_node->next;
node->prev = ref_node;
ref_node->next = node;
(node->next)->prev = node;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_insert_node_before (tListNode * node, tListNode * ref_node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
node->next = ref_node;
node->prev = ref_node->prev;
ref_node->prev = node;
(node->prev)->next = node;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
int LST_get_size (tListNode * listHead)
{
int size = 0;
tListNode * temp;
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
temp = listHead->next;
while (temp != listHead)
{
size++;
temp = temp->next;
}
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
return (size);
}
void LST_get_next_node (tListNode * ref_node, tListNode ** node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
*node = ref_node->next;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}
void LST_get_prev_node (tListNode * ref_node, tListNode ** node)
{
uint32_t primask_bit;
primask_bit = __get_PRIMASK(); /**< backup PRIMASK bit */
__disable_irq(); /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
*node = ref_node->prev;
__set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
}

View File

@@ -0,0 +1,62 @@
/**
******************************************************************************
* @file stm_list.h
* @author MCD Application Team
* @brief Header file for linked list library.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
#ifndef STM_LIST_H
#define STM_LIST_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32_wpan_common.h"
typedef __PACKED_STRUCT _tListNode {
struct _tListNode * next;
struct _tListNode * prev;
} tListNode;
void LST_init_head (tListNode * listHead);
uint8_t LST_is_empty (tListNode * listHead);
void LST_insert_head (tListNode * listHead, tListNode * node);
void LST_insert_tail (tListNode * listHead, tListNode * node);
void LST_remove_node (tListNode * node);
void LST_remove_head (tListNode * listHead, tListNode ** node );
void LST_remove_tail (tListNode * listHead, tListNode ** node );
void LST_insert_node_after (tListNode * node, tListNode * ref_node);
void LST_insert_node_before (tListNode * node, tListNode * ref_node);
int LST_get_size (tListNode * listHead);
void LST_get_next_node (tListNode * ref_node, tListNode ** node);
void LST_get_prev_node (tListNode * ref_node, tListNode ** node);
#ifdef __cplusplus
}
#endif
#endif /* STM_LIST_H */

View File

@@ -0,0 +1,384 @@
/**
******************************************************************************
* @file stm_queue.c
* @author MCD Application Team
* @brief Queue management
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
#include "stm_queue.h"
/* Private define ------------------------------------------------------------*/
/* Private typedef -------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
#define MOD(X,Y) (((X) >= (Y)) ? ((X)-(Y)) : (X))
/* Private variables ---------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
/**
* @brief Initilialze queue structure .
* @note This function is used to initialize the global queue structure.
* @param q: pointer on queue structure to be initialised
* @param queueBuffer: pointer on Queue Buffer
* @param queueSize: Size of Queue Buffer
* @param elementSize: Size of an element in the queue. if =0, the queue will manage variable sizze elements
* @retval always 0
*/
int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionFlags)
{
q->qBuff = queueBuffer;
q->first = 0;
q->last = 0; /* queueSize-1; */
q->byteCount = 0;
q->elementCount = 0;
q->queueMaxSize = queueSize;
q->elementSize = elementSize;
q->optionFlags = optionFlags;
if ((optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG) && q-> elementSize)
{
/* can not deal with splitting at the end of buffer with fixed size element */
return -1;
}
return 0;
}
/**
* @brief Add element to the queue .
* @note This function is used to add one or more element(s) to the Circular Queue .
* @param q: pointer on queue structure to be handled
* @param X; pointer on element(s) to be added
* @param elementSize: Size of element to be added to the queue. Only used if the queue manage variable size elements
* @param nbElements: number of elements in the in buffer pointed by x
* @retval pointer on last element just added to the queue, NULL if the element to be added do not fit in the queue (too big)
*/
uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements)
{
uint8_t* ptr = NULL; /* fct return ptr to the element freshly added, if no room fct return NULL */
uint16_t curElementSize = 0; /* the size of the element currently stored at q->last position */
uint8_t elemSizeStorageRoom = 0 ; /* Indicate the header (which contain only size) of element in case of varaibale size element (q->elementsize == 0) */
uint32_t curBuffPosition; /* the current position in the queue buffer */
uint32_t i; /* loop counter */
uint32_t NbBytesToCopy = 0, NbCopiedBytes = 0 ; /* Indicators for copying bytes in queue */
uint32_t eob_free_size; /* Eof End of Quque Buffer Free Size */
uint8_t wrap_will_occur = 0; /* indicate if a wrap around will occurs */
uint8_t wrapped_element_eob_size; /* In case of Wrap around, indicate size of parta of element that fit at thened of the queuue buffer */
uint16_t overhead = 0; /* In case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG or CIRCULAR_QUEUE_NO_WRAP_FLAG options,
indcate the size overhead that will be generated by adding the element with wrap management (split or no wrap ) */
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
/* retrieve the size of last element sored: the value stored at the beginning of the queue element if element size is variable otherwise take it from fixed element Size member */
if (q->byteCount)
{
curElementSize = (q->elementSize == 0) ? q->qBuff[q->last] + ((q->qBuff[MOD((q->last+1), q->queueMaxSize)])<<8) + 2 : q->elementSize;
}
/* if queue element have fixed size , reset the elementSize arg with fixed element size value */
if (q->elementSize > 0)
{
elementSize = q->elementSize;
}
eob_free_size = (q->last >= q->first) ? q->queueMaxSize - (q->last + curElementSize) : 0;
/* check how many bytes of wrapped element (if anay) are at end of buffer */
wrapped_element_eob_size = (((elementSize + elemSizeStorageRoom )*nbElements) < eob_free_size) ? 0 : (eob_free_size % (elementSize + elemSizeStorageRoom));
wrap_will_occur = wrapped_element_eob_size > elemSizeStorageRoom;
overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)) ? wrapped_element_eob_size : overhead;
overhead = (wrap_will_occur && (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)) ? elemSizeStorageRoom : overhead;
/* Store now the elements if ennough room for all elements */
if (elementSize && ((q->byteCount + ((elementSize + elemSizeStorageRoom )*nbElements) + overhead) <= q->queueMaxSize))
{
/* loop to add all elements */
for (i=0; i < nbElements; i++)
{
q->last = MOD ((q->last + curElementSize),q->queueMaxSize);
curBuffPosition = q->last;
/* store the element */
/* store first the element size if element size is variable */
if (q->elementSize == 0)
{
q->qBuff[curBuffPosition++]= elementSize & 0xFF;
curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
q->qBuff[curBuffPosition++]= (elementSize & 0xFF00) >> 8 ;
curBuffPosition = MOD(curBuffPosition, q->queueMaxSize);
q->byteCount += 2;
}
/* Identify number of bytes of copy takeing account possible wrap, in this case NbBytesToCopy will contains size that fit at end of the queue buffer */
NbBytesToCopy = MIN((q->queueMaxSize-curBuffPosition),elementSize);
/* check if no wrap (NbBytesToCopy == elementSize) or if Wrap and no spsicf option;
In this case part of data will copied at the end of the buffer and the rest a the beginning */
if ((NbBytesToCopy == elementSize) || ((NbBytesToCopy < elementSize) && (q->optionFlags == CIRCULAR_QUEUE_NO_FLAG)))
{
/* Copy First part (or emtire buffer ) from current position up to the end of the buffer queue (or before if enough room) */
memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
/* Adjust bytes count */
q->byteCount += NbBytesToCopy;
/* Wrap */
curBuffPosition = 0;
/* set NbCopiedBytes bytes with ampount copied */
NbCopiedBytes = NbBytesToCopy;
/* set the rest to copy if wrao , if no wrap will be 0 */
NbBytesToCopy = elementSize - NbBytesToCopy;
/* set the current element Size, will be used to calaculate next last position at beginning of loop */
curElementSize = (elementSize) + elemSizeStorageRoom ;
}
else if (NbBytesToCopy) /* We have a wrap to manage */
{
/* case of CIRCULAR_QUEUE_NO_WRAP_FLAG option */
if (q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG)
{
/* if element size are variable and NO_WRAP option, Invalidate end of buffer setting 0xFFFF size*/
if (q->elementSize == 0)
{
q->qBuff[curBuffPosition-2] = 0xFF;
q->qBuff[curBuffPosition-1] = 0xFF;
}
q->byteCount += NbBytesToCopy; /* invalid data at the end of buffer are take into account in byteCount */
/* No bytes coped a the end of buffer */
NbCopiedBytes = 0;
/* all element to be copied at the begnning of buffer */
NbBytesToCopy = elementSize;
/* Wrap */
curBuffPosition = 0;
/* if variable size element, invalidate end of buffer setting OxFFFF in element header (size) */
if (q->elementSize == 0)
{
q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
q->byteCount += 2;
}
}
/* case of CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG option */
else if (q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG)
{
if (q->elementSize == 0)
{
/* reset the size of current element to the nb bytes fitting at the end of buffer */
q->qBuff[curBuffPosition-2] = NbBytesToCopy & 0xFF;
q->qBuff[curBuffPosition-1] = (NbBytesToCopy & 0xFF00) >> 8 ;
/* copy the bytes */
memcpy(&q->qBuff[curBuffPosition],&x[i*elementSize],NbBytesToCopy);
q->byteCount += NbBytesToCopy;
/* set the number of copied bytes */
NbCopiedBytes = NbBytesToCopy;
/* set rest of data to be copied to begnning of buffer */
NbBytesToCopy = elementSize - NbBytesToCopy;
/* one element more dur to split in 2 elements */
q->elementCount++;
/* Wrap */
curBuffPosition = 0;
/* Set new size for rest of data */
q->qBuff[curBuffPosition++] = NbBytesToCopy & 0xFF;
q->qBuff[curBuffPosition++] = (NbBytesToCopy & 0xFF00) >> 8 ;
q->byteCount += 2;
}
else
{
/* Should not occur */
/* can not manage split Flag on Fixed size element */
/* Buffer is corrupted */
return NULL;
}
}
curElementSize = (NbBytesToCopy) + elemSizeStorageRoom ;
q->last = 0;
}
/* some remaining byte to copy */
if (NbBytesToCopy)
{
memcpy(&q->qBuff[curBuffPosition],&x[(i*elementSize)+NbCopiedBytes],NbBytesToCopy);
q->byteCount += NbBytesToCopy;
}
/* One more element */
q->elementCount++;
}
ptr = q->qBuff + (MOD((q->last+elemSizeStorageRoom ),q->queueMaxSize));
}
/* for Breakpoint only...to remove */
else
{
return NULL;
}
return ptr;
}
/**
* @brief Remove element from the queue and copy it in provided buffer
* @note This function is used to remove and element from the Circular Queue .
* @param q: pointer on queue structure to be handled
* @param elementSize: Pointer to return Size of element to be removed
* @param buffer: destination buffer where to copy element
* @retval Pointer on removed element. NULL if queue was empty
*/
uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
{
return NULL;
}
/**
* @brief Remove element from the queue.
* @note This function is used to remove and element from the Circular Queue .
* @param q: pointer on queue structure to be handled
* @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
* @retval Pointer on removed element. NULL if queue was empty
*/
uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize)
{
uint8_t elemSizeStorageRoom = 0;
uint8_t* ptr= NULL;
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
uint16_t eltSize = 0;
if (q->byteCount > 0)
{
/* retrieve element Size */
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
{
if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
{
/* all data from current position up to the end of buffer are invalid */
q->byteCount -= (q->queueMaxSize - q->first);
/* Adjust first element pos */
q->first = 0;
/* retrieve the right size after the wrap [if variable size element] */
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
}
}
/* retrieve element */
ptr = q->qBuff + (MOD((q->first + elemSizeStorageRoom), q->queueMaxSize));
/* adjust byte count */
q->byteCount -= (eltSize + elemSizeStorageRoom) ;
/* Adjust q->first */
if (q->byteCount > 0)
{
q->first = MOD((q->first+ eltSize + elemSizeStorageRoom ), q->queueMaxSize);
}
/* adjust element count */
--q->elementCount;
}
if (elementSize != NULL)
{
*elementSize = eltSize;
}
return ptr;
}
/**
* @brief "Sense" first element of the queue, without removing it and copy it in provided buffer
* @note This function is used to return a pointer on the first element of the queue without removing it.
* @param q: pointer on queue structure to be handled
* @param elementSize: Pointer to return Size of element to be removed
* @param buffer: destination buffer where to copy element
* @retval Pointer on sensed element. NULL if queue was empty
*/
uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer)
{
return NULL;
}
/**
* @brief "Sense" first element of the queue, without removing it.
* @note This function is used to return a pointer on the first element of the queue without removing it.
* @param q: pointer on queue structure to be handled
* @param elementSize: Pointer to return Size of element to be removed (ignored if NULL)
* @retval Pointer on sensed element. NULL if queue was empty
*/
uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize)
{
uint8_t elemSizeStorageRoom = 0;
uint8_t* x= NULL;
elemSizeStorageRoom = (q->elementSize == 0) ? 2 : 0;
uint16_t eltSize = 0;
uint32_t FirstElemetPos = 0;
if (q->byteCount > 0)
{
FirstElemetPos = q->first;
eltSize = (q->elementSize == 0) ? q->qBuff[q->first] + ((q->qBuff[MOD((q->first+1), q->queueMaxSize)])<<8) : q->elementSize;
if ((q->optionFlags & CIRCULAR_QUEUE_NO_WRAP_FLAG) && !(q->optionFlags & CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG))
{
if (((eltSize == 0xFFFF) && q->elementSize == 0 ) ||
((q->first > q->last) && q->elementSize && ((q->queueMaxSize - q->first) < q->elementSize)))
{
/* all data from current position up to the end of buffer are invalid */
FirstElemetPos = 0; /* wrap to the begiining of buffer */
/* retrieve the right size after the wrap [if variable size element] */
eltSize = (q->elementSize == 0) ? q->qBuff[FirstElemetPos]+ ((q->qBuff[MOD((FirstElemetPos+1), q->queueMaxSize)])<<8) : q->elementSize;
}
}
/* retrieve element */
x = q->qBuff + (MOD((FirstElemetPos + elemSizeStorageRoom), q->queueMaxSize));
}
if (elementSize != NULL)
{
*elementSize = eltSize;
}
return x;
}
/**
* @brief Check if queue is empty.
* @note This function is used to to check if the queue is empty.
* @param q: pointer on queue structure to be handled
* @retval TRUE (!0) if the queue is empyu otherwise FALSE (0)
*/
int CircularQueue_Empty(queue_t *q)
{
int ret=FALSE;
if (q->byteCount <= 0)
{
ret=TRUE;
}
return ret;
}
int CircularQueue_NbElement(queue_t *q)
{
return q->elementCount;
}

View File

@@ -0,0 +1,69 @@
/**
******************************************************************************
* @file stm_queue.h
* @author MCD Application Team
* @brief Header for stm_queue.c
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM_QUEUE_H
#define __STM_QUEUE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
/* Exported define -----------------------------------------------------------*/
/* Options flags */
#define CIRCULAR_QUEUE_NO_FLAG 0
#define CIRCULAR_QUEUE_NO_WRAP_FLAG 1
#define CIRCULAR_QUEUE_SPLIT_IF_WRAPPING_FLAG 2
/* Exported types ------------------------------------------------------------*/
typedef struct {
uint8_t* qBuff; /* queue buffer, , provided by init fct */
uint32_t queueMaxSize; /* size of the queue, provided by init fct (in bytes)*/
uint16_t elementSize; /* -1 variable. If variable element size the size is stored in the 4 first of the queue element */
uint32_t first; /* position of first element */
uint32_t last; /* position of last element */
uint32_t byteCount; /* number of bytes in the queue */
uint32_t elementCount; /* number of element in the queue */
uint8_t optionFlags; /* option to enable specific features */
} queue_t;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
int CircularQueue_Init(queue_t *q, uint8_t* queueBuffer, uint32_t queueSize, uint16_t elementSize, uint8_t optionlags);
uint8_t* CircularQueue_Add(queue_t *q, uint8_t* x, uint16_t elementSize, uint32_t nbElements);
uint8_t* CircularQueue_Remove(queue_t *q, uint16_t* elementSize);
uint8_t* CircularQueue_Sense(queue_t *q, uint16_t* elementSize);
int CircularQueue_Empty(queue_t *q);
int CircularQueue_NbElement(queue_t *q);
uint8_t* CircularQueue_Remove_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer);
uint8_t* CircularQueue_Sense_Copy(queue_t *q, uint16_t* elementSize, uint8_t* buffer);
/******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
#ifdef __cplusplus
}
#endif
#endif /* __STM_QUEUE_H */

View File

@@ -0,0 +1,92 @@
/**
******************************************************************************
* @file temp_measurement.c
* @author MCD Application Team
* @brief Temp measurement module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
/* Common utilites */
#include "utilities_common.h"
#if (USE_TEMPERATURE_BASED_RADIO_CALIBRATION == 1)
/* Own header file */
#include "temp_measurement.h"
/* ADC Controller module */
#include "adc_ctrl.h"
#include "adc_ctrl_conf.h"
/* Link layer interfaces */
#include "ll_intf.h"
#include "ll_intf_cmn.h"
/* Private defines -----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variables ----------------------------------------------------------*/
/* Error Handler */
extern void Error_Handler(void);
/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/
TEMPMEAS_Cmd_Status_t TEMPMEAS_Init (void)
{
TEMPMEAS_Cmd_Status_t error = TEMPMEAS_UNKNOWN;
ADCCTRL_Cmd_Status_t eReturn = ADCCTRL_UNKNOWN;
eReturn = ADCCTRL_RegisterHandle (&LLTempRequest_Handle);
if ((ADCCTRL_HANDLE_ALREADY_REGISTERED == eReturn) ||
(ADCCTRL_OK == eReturn))
{
error = TEMPMEAS_OK;
}
else
{
error = TEMPMEAS_ADC_INIT;
}
return error;
}
void TEMPMEAS_RequestTemperatureMeasurement (void)
{
int16_t temperature_value = 0;
/* Enter limited critical section : disable all the interrupts with priority higher than RCC one
* Concerns link layer interrupts (high and SW low) or any other high priority user system interrupt
*/
UTILS_ENTER_LIMITED_CRITICAL_SECTION(RCC_INTR_PRIO<<4);
/* Request ADC IP activation */
ADCCTRL_RequestIpState(&LLTempRequest_Handle, ADC_ON);
/* Get temperature from ADC dedicated channel */
ADCCTRL_RequestTemperature (&LLTempRequest_Handle,
&temperature_value);
/* Request ADC IP deactivation */
ADCCTRL_RequestIpState(&LLTempRequest_Handle, ADC_OFF);
/* Give shifted value of the temperature to the link layer */
ll_intf_cmn_set_temperature_value((uint32_t)(temperature_value + TEMPMEAS_MIN_TEMP_LIMIT));
/* Exit limited critical section */
UTILS_EXIT_LIMITED_CRITICAL_SECTION();
}
#endif /* USE_TEMPERATURE_BASED_RADIO_CALIBRATION */
/* Private Functions Definition ------------------------------------------------------*/

View File

@@ -0,0 +1,74 @@
/**
******************************************************************************
* @file temp_measurement.h
* @author MCD Application Team
* @brief Header for temp_measurement.c module
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef TEMP_MEASUREMENT_H
#define TEMP_MEASUREMENT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"
/* Exported defines ----------------------------------------------------------*/
/**
* @brief Minimum operating temperature limit absolute value
*
* @details I.e.: Operating temperature is between -40C and 105degC,
* Minimum value expected is 40u.
*/
#define TEMPMEAS_MIN_TEMP_LIMIT ((uint32_t)40u)
/* Exported types ------------------------------------------------------------*/
/**
* @brief Temperature Measurement command status codes
*/
typedef enum TEMPMEAS_Cmd_Status
{
TEMPMEAS_OK,
TEMPMEAS_NOK,
TEMPMEAS_ADC_INIT,
TEMPMEAS_UNKNOWN,
} TEMPMEAS_Cmd_Status_t;
/* Exported constants --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions prototypes ---------------------------------------------*/
/**
* @brief Initialize the temperature measurement
*
* @retval Operation state
*/
TEMPMEAS_Cmd_Status_t TEMPMEAS_Init (void);
/**
* @brief Request temperature measurement
* @param None
* @retval None
*/
void TEMPMEAS_RequestTemperatureMeasurement (void);
#ifdef __cplusplus
}
#endif
#endif /* TEMP_MEASUREMENT_H */

View File

@@ -0,0 +1,163 @@
/**
******************************************************************************
* @file utilities_common.h
* @author MCD Application Team
* @brief Common file to utilities
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef UTILITIES_COMMON_H
#define UTILITIES_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "app_conf.h"
/* -------------------------------- *
* Basic definitions *
* -------------------------------- */
#undef NULL
#define NULL 0
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE (!0)
/* -------------------------------- *
* Critical Section definition *
* -------------------------------- */
#undef BACKUP_PRIMASK
#define BACKUP_PRIMASK() uint32_t primask_bit= __get_PRIMASK()
#undef DISABLE_IRQ
#define DISABLE_IRQ() __disable_irq()
#undef RESTORE_PRIMASK
#define RESTORE_PRIMASK() __set_PRIMASK(primask_bit)
/* -------------------------------- *
* Macro delimiters *
* -------------------------------- */
#undef M_BEGIN
#define M_BEGIN do {
#undef M_END
#define M_END } while(0)
/* -------------------------------- *
* Some useful macro definitions *
* -------------------------------- */
#undef MAX
#define MAX( x, y ) (((x)>(y))?(x):(y))
#undef MIN
#define MIN( x, y ) (((x)<(y))?(x):(y))
#undef MODINC
#define MODINC( a, m ) M_BEGIN (a)++; if ((a)>=(m)) (a)=0; M_END
#undef MODDEC
#define MODDEC( a, m ) M_BEGIN if ((a)==0) (a)=(m); (a)--; M_END
#undef MODADD
#define MODADD( a, b, m ) M_BEGIN (a)+=(b); if ((a)>=(m)) (a)-=(m); M_END
#undef MODSUB
#define MODSUB( a, b, m ) MODADD( a, (m)-(b), m )
#undef ALIGN
#ifdef WIN32
#define ALIGN(n)
#else
#define ALIGN(n) __attribute__((aligned(n)))
#endif
#undef PAUSE
#define PAUSE( t ) M_BEGIN \
volatile int _i; \
for ( _i = t; _i > 0; _i -- ); \
M_END
#undef DIVF
#define DIVF( x, y ) ((x)/(y))
#undef DIVC
#define DIVC( x, y ) (((x)+(y)-1)/(y))
#undef DIVR
#define DIVR( x, y ) (((x)+((y)/2))/(y))
#undef SHRR
#define SHRR( x, n ) ((((x)>>((n)-1))+1)>>1)
#undef BITN
#define BITN( w, n ) (((w)[(n)/32] >> ((n)%32)) & 1)
#undef BITNSET
#define BITNSET( w, n, b ) M_BEGIN (w)[(n)/32] |= ((U32)(b))<<((n)%32); M_END
/* -------------------------------- *
* Section attribute *
* -------------------------------- */
#define PLACE_IN_SECTION( __x__ ) __attribute__((section (__x__)))
#ifdef __cplusplus
}
#endif
#define SYS_WAITING_CYCLES_25() do {\
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");__asm("mov r0, r0");\
} while(0)
#define SYS_WAITING_RNGCLK_DEACTIVATION() do {\
for(volatile unsigned int cpt = 178 ; cpt!=0 ; --cpt);\
} while(0)
#define STM32WBA5x_DEFAULT_SCA_RANGE (0)
#define STM32WBA5x_REV_ID_A_SCA_RANGE (0)
#define STM32WBA5x_REV_ID_B_SCA_RANGE (0)
#ifdef STM32WBA65xx
#define STM32WBA6x_SCA_RANGE (0)
#endif
/* Macro helper for optimizing by speed specific functions.
* For IAR only: The functions with this definition will be optimized
* by speed only if the project uses a High optimisation level.
*/
#if defined(__IAR_SYSTEMS_ICC__)
#define OPTIMIZED _Pragma("optimize=speed")
#elif defined(__clang__)
#define OPTIMIZED _Pragma("pragma Ofast")
#elif defined(__GNUC__)
#define OPTIMIZED __attribute__((optimize("Ofast")))
#endif
#define UTIL_UNUSED(X) (void)X /* To avoid gcc/g++ warnings */
#endif /* UTILITIES_COMMON_H */

View File

@@ -0,0 +1,131 @@
;********************************************************************************
;* File Name : stm32wbaxx_ResetHandler.s
;* Author : MCD Application Team
;* Description : STM32WBA5xx Ultra Low Power Devices specific
; Reset handler for connectivity applications.
; EWARM toolchain.
;********************************************************************************
;* @attention
;*
;* Copyright (c) 2022 STMicroelectronics.
;* All rights reserved.
;*
;* This software is licensed under terms that can be found in the LICENSE file
;* in the root directory of this software component.
;* If no LICENSE file comes with this software, it is provided AS-IS.
;*
;*******************************************************************************
;
; Cortex-M version
;
EXTERN __iar_program_start
EXTERN SystemInit
EXTERN is_boot_from_standby
EXTERN SYS_WAITING_CYCLES_25
IMPORT backup_MSP
IMPORT register_backup_table
IMPORT register_backup_table_size
EXPORT CPUcontextSave
EXPORT backup_system_register
EXPORT restore_system_register
PUBLIC Reset_Handler
SECTION .text:CODE:NOROOT:REORDER(2)
Reset_Handler
/* If we exit from standby mode, restore CPU context and jump to asleep point. */
BL is_boot_from_standby
CMP R0, #1
BEQ CPUcontextRestore
/* buffer for local variables (up to 10)from is_boot_from_standby*/
SUB SP, SP, #0x28
/* end of specific code section for standby */
LDR R0, =SystemInit
BLX R0
LDR R0, =__iar_program_start
BX R0
/* These 2 functions are designed to save and then restore CPU context. */
CPUcontextSave
PUSH { R4 - R12, LR } /* store R4 to R12 and LR (10 words) onto C stack */
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
MOV R3, SP /* load the stack pointer into R3 */
STR R3, [R4] /* store the MSP into backup_MSP */
DSB
WFI /* all saved, trigger deep sleep */
CPUcontextRestore
/* Even if we fall through the WFI instruction, we will immediately
* execute a context restore and end up where we left off with no
* ill effects. Normally at this point the core will either be
* powered off or reset (depending on the deep sleep level). */
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
LDR R4, [R4] /* load the SP from backup_MSP */
MOV SP, R4 /* restore the SP from R4 */
POP { R4 - R12, PC } /* load R4 to R12 and PC (10 words) from C stack */
backup_system_register
/* R0 -> register_backup_table array current item address */
/* R1 -> loop counter (from register_backup_table_size to 0) */
/* R2 -> register_backup_table array current item value */
backup_loop_init:
LDR R0, =register_backup_table /* R0 points to the first array item */
LDR R1, =register_backup_table_size
LDR R1, [R1] /* R1 contains the number of registers in the array */
backup_loop_iter:
/* Offset processing */
LDR R2, [R0], #4 /* R2 contains the register_backup_table current item (register address) */
/* R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address) */
/* Register value backup */
LDR R2, [R2] /* R2 contains now the register value to backup */
PUSH {R2} /* Push register value into the stack */
/* Loop iteration control */
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
BNE backup_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
backup_loop_end:
BX LR /* Return to caller */
restore_system_register
/* R0 -> register_backup_table array current item address */
/* R1 -> loop counter (from register_backup_table_size to 0) */
/* R2 -> register_backup_table array current item value */
restore_loop_init:
LDR R0, =register_backup_table /* R0 points to the first array item */
/* Reverse loop: counter initial value processing */
LDR R1, =register_backup_table_size
LDR R1, [R1] /* R1 contains the number of registers in the array */
SUB R1, #1 /* R1 now contains last array item index (register_backup_table_size - 1) */
/* Reverse loop: apply offset to current array index (point to last array element) */
ADD R0, R1, LSL #2 /* R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4) */
ADD R1, #1 /* Re-add 1 to R1 (array length) */
/* Reverse loop */
restore_loop_iter:
/* Offset processing */
LDR R2, [R0], #-4 /* R2 contains the register_backup_table current item (register address) */
/* R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address) */
/* Register value restoration */
POP {R3} /* Head of stack popped into R3. R3 contains register value to restore */
STR R3, [R2] /* Write backuped value into the register */
/* Loop iteration control */
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
BNE restore_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
restore_loop_end:
BX LR /* Return to caller */
/* end of specific code section for standby */
END

View File

@@ -0,0 +1,189 @@
/**
******************************************************************************
* File Name : stm32wbaxx_ResetHandler.s
* Author : MCD Application Team
* Description : STM32WBA5xx Ultra Low Power Devices specific
* Reset handler for connectivity applications.
GCC toolchain.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*
* Cortex-M version
*
******************************************************************************
*/
.syntax unified
.cpu cortex-m33
.fpu softvfp
.thumb
.extern SystemInit
.extern is_boot_from_standby
.extern SYS_WAITING_CYCLES_25
.global backup_system_register
.global restore_system_register
/* INIT_BSS macro is used to fill the specified region [start : end] with zeros */
.macro INIT_BSS start, end
ldr r0, =\start
ldr r1, =\end
movs r3, #0
bl LoopFillZerobss
.endm
/* INIT_DATA macro is used to copy data in the region [start : end] starting from 'src' */
.macro INIT_DATA start, end, src
ldr r0, =\start
ldr r1, =\end
ldr r2, =\src
movs r3, #0
bl LoopCopyDataInit
.endm
.section .text.data_initializers
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
bx lr
FillZerobss:
str r3, [r0]
adds r0, r0, #4
LoopFillZerobss:
cmp r0, r1
bcc FillZerobss
bx lr
.section .text.Reset_Handler
.global Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* set stack pointer */
/* If we exit from standby mode, restore CPU context and jump to asleep point. */
BL is_boot_from_standby
CMP R0, #1
BEQ CPUcontextRestore
/* buffer for local variables (up to 10)from is_boot_from_standby*/
SUB SP, SP, #0x28
/* end of specific code section for standby */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
INIT_DATA _sdata, _edata, _sidata
/* Zero fill the bss segments. */
INIT_BSS _sbss, _ebss
/* Call static constructors */
bl __libc_init_array
/* Call the application s entry point.*/
bl main
LoopForever:
b LoopForever
/* These 2 functions are designed to save and then restore CPU context. */
.global CPUcontextSave
.type CPUcontextSave, %function
CPUcontextSave:
PUSH { R4 - R12, LR } /* store R4 to R12 and LR (10 words) onto C stack */
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
MOV R3, SP /* load the stack pointer into R3 */
STR R3, [R4] /* store the MSP into backup_MSP */
DSB
WFI /* all saved, trigger deep sleep */
CPUcontextRestore:
/* Even if we fall through the WFI instruction, we will immediately
* execute a context restore and end up where we left off with no
* ill effects. Normally at this point the core will either be
* powered off or reset (depending on the deep sleep level). */
LDR R4, =backup_MSP /* load address of backup_MSP into R4 */
LDR R4, [R4] /* load the SP from backup_MSP */
MOV SP, R4 /* restore the SP from R4 */
POP { R4 - R12, PC } /* load R4 to R12 and PC (10 words) from C stack */
backup_system_register:
/* R0 -> register_backup_table array current item address */
/* R1 -> loop counter (from register_backup_table_size to 0) */
/* R2 -> register_backup_table array current item value */
backup_loop_init:
LDR R0, =register_backup_table /* R0 points to the first array item */
LDR R1, =register_backup_table_size
LDR R1, [R1] /* R1 contains the number of registers in the array */
backup_loop_iter:
/* Offset processing */
LDR R2, [R0], #4 /* R2 contains the register_backup_table current item (register address) */
/* R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address) */
/* Register value backup */
LDR R2, [R2] /* R2 contains now the register value to backup */
PUSH {R2} /* Push register value into the stack */
/* Loop iteration control */
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
BNE backup_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
backup_loop_end:
BX LR /* Return to caller */
restore_system_register:
/* R0 -> register_backup_table array current item address */
/* R1 -> loop counter (from register_backup_table_size to 0) */
/* R2 -> register_backup_table array current item value */
restore_loop_init:
LDR R0, =register_backup_table /* R0 points to the first array item */
/* Reverse loop: counter initial value processing */
LDR R1, =register_backup_table_size
LDR R1, [R1] /* R1 contains the number of registers in the array */
SUB R1, #1 /* R1 now contains last array item index (register_backup_table_size - 1) */
/* Reverse loop: apply offset to current array index (point to last array element) */
LSL R1, #2 /* Left shift R1 by 2 */
ADD R0, R1 /* R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4) */
LSR R1, #2 /* Reverse left shift operation on R1 */
ADD R1, #1 /* Re-add 1 to R1 (array length) */
/* Reverse loop */
restore_loop_iter:
/* Offset processing */
LDR R2, [R0], #-4 /* R2 contains the register_backup_table current item (register address) */
/* R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address) */
/* Register value restoration */
POP {R3} /* Head of stack popped into R3. R3 contains register value to restore */
STR R3, [R2] /* Write backuped value into the register */
/* Loop iteration control */
SUBS R1, #1 /* Decrement loop counter by 1 and update APSR (Application Processor Status Register) */
BNE restore_loop_iter /* Loop continues until Z flag is set (still array item to handle) */
restore_loop_end:
BX LR /* Return to caller */
/* end of specific code section for standby */
.end

View File

@@ -0,0 +1,134 @@
;********************************************************************************
;* File Name : stm32wbaxx_ResetHandler.s
;* Author : MCD Application Team
;* Description : STM32WBA5xx Ultra Low Power Devices specific
; Reset handler for connectivity applications.
; MDK-ARM toolchain.
;********************************************************************************
;* @attention
;*
;* Copyright (c) 2022 STMicroelectronics.
;* All rights reserved.
;*
;* This software is licensed under terms that can be found in the LICENSE file
;* in the root directory of this software component.
;* If no LICENSE file comes with this software, it is provided AS-IS.
;*
;*******************************************************************************
;
; Cortex-M version
;
PRESERVE8
THUMB
AREA |.text|, CODE, READONLY
; Reset_Handler
Reset_Handler PROC
EXPORT Reset_Handler
IMPORT SystemInit
IMPORT __main
IMPORT is_boot_from_standby
IMPORT backup_MSP
IMPORT register_backup_table
IMPORT register_backup_table_size
EXPORT CPUcontextSave
EXPORT backup_system_register
EXPORT restore_system_register
; If we exit from standby mode, restore CPU context and jump to asleep point.
BL is_boot_from_standby
CMP R0, #1
BEQ CPUcontextRestore
; buffer for local variables (up to 10)from is_boot_from_standby.
SUB SP, SP, #0x28
; end of specific code section for standby
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; These 2 functions are designed to save and then restore CPU context.
CPUcontextSave
PUSH { R4 - R12, lr } ; store R4 to R12 and LR (10 words) onto C stack
LDR R4, =backup_MSP ; load address of backup_MSP into R4
MOV R3, SP ; load the stack pointer into R3
STR R3, [R4] ; store the MSP into backup_MSP
DSB
WFI ; all saved, trigger deep sleep
CPUcontextRestore
; Even if we fall through the WFI instruction, we will immediately
; execute a context restore and end up where we left off with no
; ill effects. Normally at this point the core will either be
; powered off or reset (depending on the deep sleep level).
LDR R4, =backup_MSP ; load address of backup_MSP into R4.
LDR R4, [R4] ; load the SP from backup_MSP.
MOV SP, R4 ; restore the SP from R4.
POP { R4 - R12, PC } ; load R4-R12 and PC (10 words) from C stack
; end of specific code section for standby.
backup_system_register
; R0 -> register_backup_table array current item address
; R1 -> loop counter (from register_backup_table_size to 0)
; R2 -> register_backup_table array current item value
backup_loop_init
LDR R0, =register_backup_table ; R0 points to the first array item
LDR R1, =register_backup_table_size
LDR R1, [R1] ; R1 contains the number of registers in the array
backup_loop_iter
; Offset processing
LDR R2, [R0], #4 ; R2 contains the register_backup_table current item (register address)
; R0 points to the next register_backup_table item (uint32_t items -> 4 bytes added to previous address)
; Register value backup
LDR R2, [R2] ; R2 contains now the register value to backup
PUSH {R2} ; Push register value into the stack
; Loop iteration control
SUBS R1, #1 ; Decrement loop counter by 1 and update APSR (Application Processor Status Register)
BNE backup_loop_iter ; Loop continues until Z flag is set (still array item to handle)
backup_loop_end
BX LR ; Return to caller
restore_system_register
; R0 -> register_backup_table array current item address
; R1 -> loop counter (from register_backup_table_size to 0)
; R2 -> register_backup_table array current item value
restore_loop_init
LDR R0, =register_backup_table ; R0 points to the first array item
; Reverse loop: counter initial value processing
LDR R1, =register_backup_table_size
LDR R1, [R1] ; R1 contains the number of registers in the array
SUB R1, #1 ; R1 now contains last array item index (register_backup_table_size - 1)
; Reverse loop: apply offset to current array index (point to last array element)
ADD R0, R1, LSL #2 ; R0 now points to last array item (register_backup_table + (register_backup_table_size - 1) * 4)
ADD R1, #1 ; Re-add 1 to R1 (array length)
; Reverse loop
restore_loop_iter
; Offset processing
LDR R2, [R0], #-4 ; R2 contains the register_backup_table current item (register address)
; R0 now points to the previous register_backup_table item (uint32_t items -> 4 bytes subtracted to previous address)
; Register value restoration
POP {R3} ; Head of stack popped into R3. R3 contains register value to restore
STR R3, [R2] ; Write backuped value into the register
; Loop iteration control
SUBS R1, #1 ; Decrement loop counter by 1 and update APSR (Application Processor Status Register)
BNE restore_loop_iter ; Loop continues until Z flag is set (still array item to handle)
restore_loop_end
BX LR ; Return to caller
END