mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
aes/sha/mpi: Bugfix a use of shared registers.
This commit resolves a blocking in esp_aes_block function. Introduce: The problem was in the fact that AES is switched off at the moment when he should give out the processed data. But because of the disabled, the operation can not be completed successfully, there is an infinite hang. The reason for this behavior is that the registers for controlling the inclusion of AES, SHA, MPI have shared registers and they were not protected from sharing. Fix some related issue with shared using of AES SHA RSA accelerators. Closes: https://github.com/espressif/esp-idf/issues/2295#issuecomment-432898137
This commit is contained in:

committed by
bot

parent
fb7ba1baa0
commit
8bba348528
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include <stdio.h>
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
|
||||
/* AES uses a spinlock mux not a lock as the underlying block operation
|
||||
@@ -50,26 +51,16 @@ static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
void esp_aes_acquire_hardware( void )
|
||||
{
|
||||
/* newlib locks lazy initialize on ESP-IDF */
|
||||
portENTER_CRITICAL(&aes_spinlock);
|
||||
|
||||
/* Enable AES hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Clear reset on digital signature & secure boot units,
|
||||
otherwise AES unit is held in reset also. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_AES
|
||||
| DPORT_PERI_EN_DIGITAL_SIGNATURE
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
periph_module_enable(PERIPH_AES_MODULE);
|
||||
}
|
||||
|
||||
void esp_aes_release_hardware( void )
|
||||
{
|
||||
/* Disable AES hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Don't return other units to reset, as this pulls
|
||||
reset on RSA & SHA units, respectively. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
periph_module_disable(PERIPH_AES_MODULE);
|
||||
|
||||
portEXIT_CRITICAL(&aes_spinlock);
|
||||
}
|
||||
@@ -116,7 +107,10 @@ static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
|
||||
const uint32_t MODE_DECRYPT_BIT = 4;
|
||||
unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT;
|
||||
|
||||
memcpy((uint32_t *)AES_KEY_BASE, ctx->key, ctx->key_bytes);
|
||||
for (int i = 0; i < ctx->key_bytes/4; ++i) {
|
||||
DPORT_REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i));
|
||||
}
|
||||
|
||||
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "rom/ets_sys.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type) {
|
||||
return SHA_1_LOAD_REG + sha_type * 0x10;
|
||||
@@ -160,11 +161,7 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine)
|
||||
|
||||
if (sha_engines_all_idle()) {
|
||||
/* Enable SHA hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
/* also clear reset on secure boot, otherwise SHA is held in reset */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_SHA
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
periph_module_enable(PERIPH_SHA_MODULE);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
ets_sha_enable();
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
@@ -188,9 +185,7 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
|
||||
|
||||
if (sha_engines_all_idle()) {
|
||||
/* Disable SHA hardware */
|
||||
/* Don't assert reset on secure boot, otherwise AES is held in reset */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
periph_module_disable(PERIPH_SHA_MODULE);
|
||||
}
|
||||
|
||||
_lock_release(&state_change_lock);
|
||||
@@ -276,9 +271,9 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
||||
|
||||
SHA_CTX ctx;
|
||||
ets_sha_init(&ctx);
|
||||
esp_sha_lock_memory_block();
|
||||
while(ilen > 0) {
|
||||
size_t chunk_len = (ilen > block_len) ? block_len : ilen;
|
||||
esp_sha_lock_memory_block();
|
||||
esp_sha_wait_idle();
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
@@ -286,11 +281,9 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
||||
ets_sha_update(&ctx, sha_type, input, chunk_len * 8);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
esp_sha_unlock_memory_block();
|
||||
input += chunk_len;
|
||||
ilen -= chunk_len;
|
||||
}
|
||||
esp_sha_lock_memory_block();
|
||||
esp_sha_wait_idle();
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
|
287
components/esp32/test/test_aes_sha_rsa.c
Normal file
287
components/esp32/test/test_aes_sha_rsa.c
Normal file
@@ -0,0 +1,287 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "esp_types.h"
|
||||
#include "esp_clk.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_timer.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "unity.h"
|
||||
#include "rom/uart.h"
|
||||
#include "rom/sha.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_log.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "hwcrypto/sha.h"
|
||||
#include "hwcrypto/aes.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
|
||||
static const char *TAG = "test";
|
||||
static volatile bool exit_flag = false;
|
||||
#define TASK_STACK_SIZE (8*1024)
|
||||
|
||||
static void aes_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
ESP_LOGI(TAG, "aes_task is started");
|
||||
esp_aes_context ctx = {
|
||||
.key_bytes = 16,
|
||||
.key = {101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116}
|
||||
};
|
||||
const unsigned char input[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
unsigned char output[16];
|
||||
unsigned char output2[16];
|
||||
while (exit_flag == false) {
|
||||
memset(output, 0, sizeof(output));
|
||||
memset(output, 0, sizeof(output2));
|
||||
esp_internal_aes_encrypt(&ctx, input, output);
|
||||
esp_internal_aes_decrypt(&ctx, output, output2);
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(input, output2, sizeof(input), "AES must match");
|
||||
}
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void sha_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
ESP_LOGI(TAG, "sha_task is started");
|
||||
const char *input = "Space!#$%&()*+,-.0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789";
|
||||
unsigned char output[64];
|
||||
unsigned char output_origin[64];
|
||||
esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output);
|
||||
memcpy(output_origin, output, sizeof(output));
|
||||
while (exit_flag == false) {
|
||||
memset(output, 0, sizeof(output));
|
||||
esp_sha(SHA2_512, (const unsigned char *)input, sizeof(input), output);
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "SHA256 must match");
|
||||
}
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void mbedtls_sha256_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
ESP_LOGI(TAG, "mbedtls_sha256_task is started");
|
||||
const char *input = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789Space!#$%&()*+,-.0123456789:;<=>?";
|
||||
mbedtls_sha256_context sha256_ctx;
|
||||
unsigned char output[32];
|
||||
unsigned char output_origin[32];
|
||||
|
||||
mbedtls_sha256_init(&sha256_ctx);
|
||||
memset(output, 0, sizeof(output));
|
||||
mbedtls_sha256_starts_ret(&sha256_ctx, false);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mbedtls_sha256_update_ret(&sha256_ctx, (unsigned char *)input, 100);
|
||||
}
|
||||
mbedtls_sha256_finish_ret(&sha256_ctx, output);
|
||||
memcpy(output_origin, output, sizeof(output));
|
||||
|
||||
while (exit_flag == false) {
|
||||
mbedtls_sha256_init(&sha256_ctx);
|
||||
memset(output, 0, sizeof(output));
|
||||
mbedtls_sha256_starts_ret(&sha256_ctx, false);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
mbedtls_sha256_update_ret(&sha256_ctx, (unsigned char *)input, 100);
|
||||
}
|
||||
mbedtls_sha256_finish_ret(&sha256_ctx, output);
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "MBEDTLS SHA256 must match");
|
||||
}
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test shared using AES SHA512 SHA256", "[hw_crypto]")
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
const int max_tasks = 6;
|
||||
#else
|
||||
const int max_tasks = 3;
|
||||
#endif
|
||||
xSemaphoreHandle exit_sema[max_tasks];
|
||||
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
exit_sema[i] = xSemaphoreCreateBinary();
|
||||
}
|
||||
exit_flag = false;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[3], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[4], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[5], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
#else
|
||||
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for 10s ...");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
// set exit flag to let thread exit
|
||||
exit_flag = true;
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sema not released by test task");
|
||||
}
|
||||
vSemaphoreDelete(exit_sema[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void rsa_task(void *pvParameters)
|
||||
{
|
||||
xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters;
|
||||
ESP_LOGI(TAG, "rsa_task is started");
|
||||
while (exit_flag == false) {
|
||||
mbedtls_rsa_self_test(0);
|
||||
}
|
||||
xSemaphoreGive(*sema);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("Test shared using AES RSA", "[hw_crypto]")
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
const int max_tasks = 2;
|
||||
#else
|
||||
const int max_tasks = 2;
|
||||
#endif
|
||||
xSemaphoreHandle exit_sema[max_tasks];
|
||||
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
exit_sema[i] = xSemaphoreCreateBinary();
|
||||
}
|
||||
exit_flag = false;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
#else
|
||||
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for 10s ...");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
// set exit flag to let thread exit
|
||||
exit_flag = true;
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sema not released by test task");
|
||||
}
|
||||
vSemaphoreDelete(exit_sema[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test shared using SHA512 RSA", "[hw_crypto]")
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
const int max_tasks = 2;
|
||||
#else
|
||||
const int max_tasks = 2;
|
||||
#endif
|
||||
xSemaphoreHandle exit_sema[max_tasks];
|
||||
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
exit_sema[i] = xSemaphoreCreateBinary();
|
||||
}
|
||||
exit_flag = false;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 2, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
#else
|
||||
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for 10s ...");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
// set exit flag to let thread exit
|
||||
exit_flag = true;
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sema not released by test task");
|
||||
}
|
||||
vSemaphoreDelete(exit_sema[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test shared using SHA256 RSA", "[hw_crypto]")
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
const int max_tasks = 2;
|
||||
#else
|
||||
const int max_tasks = 2;
|
||||
#endif
|
||||
xSemaphoreHandle exit_sema[max_tasks];
|
||||
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
exit_sema[i] = xSemaphoreCreateBinary();
|
||||
}
|
||||
exit_flag = false;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
#else
|
||||
xTaskCreate(&mbedtls_sha256_task, "mbedtls_sha256_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for 10s ...");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
// set exit flag to let thread exit
|
||||
exit_flag = true;
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sema not released by test task");
|
||||
}
|
||||
vSemaphoreDelete(exit_sema[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test shared using AES SHA RSA", "[hw_crypto]")
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
const int max_tasks = 3;
|
||||
#else
|
||||
const int max_tasks = 3;
|
||||
#endif
|
||||
xSemaphoreHandle exit_sema[max_tasks];
|
||||
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
exit_sema[i] = xSemaphoreCreateBinary();
|
||||
}
|
||||
exit_flag = false;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
xTaskCreatePinnedToCore(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL, 0);
|
||||
xTaskCreatePinnedToCore(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL, 1);
|
||||
#else
|
||||
xTaskCreate(&aes_task, "aes_task", TASK_STACK_SIZE, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&sha_task, "sha_task", TASK_STACK_SIZE, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
xTaskCreate(&rsa_task, "rsa_task", TASK_STACK_SIZE, &exit_sema[2], UNITY_FREERTOS_PRIORITY - 1, NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Waiting for 10s ...");
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
// set exit flag to let thread exit
|
||||
exit_flag = true;
|
||||
for (int i = 0; i < max_tasks; ++i) {
|
||||
if (!xSemaphoreTake(exit_sema[i], 2000/portTICK_PERIOD_MS)) {
|
||||
TEST_FAIL_MESSAGE("exit_sema not released by test task");
|
||||
}
|
||||
vSemaphoreDelete(exit_sema[i]);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user