mirror of https://github.com/ARMmbed/mbed-os.git
Support TRNG
To change TRNG security state, we need to: 1. Change CRPT/CRYPTO bit in NVIC/SCU in partition_M2351.h 2. Add/remove TRNG in device_has list in targets.json to match partition_M2351.hpull/7631/head
parent
b86c957c0d
commit
bce2b6460d
|
@ -112,6 +112,11 @@ struct pwmout_s {
|
|||
struct sleep_s {
|
||||
int powerdown;
|
||||
};
|
||||
|
||||
struct trng_s {
|
||||
uint8_t dummy;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,329 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2018 Nuvoton
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_critical.h"
|
||||
#include "mbed_error.h"
|
||||
#include <limits.h>
|
||||
#include "nu_modutil.h"
|
||||
#include "nu_bitutil.h"
|
||||
#include "crypto-misc.h"
|
||||
|
||||
/* NOTE: There's inconsistency in cryptography related naming, Crpt or Crypto. For example, cryptography IRQ
|
||||
* handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override default cryptography IRQ handler, see
|
||||
* device/startup_{CHIP}.c for its name or call NVIC_SetVector regardless of its name. */
|
||||
void CRPT_IRQHandler();
|
||||
|
||||
/* Track if AES H/W is available */
|
||||
static uint16_t crypto_aes_avail = 1;
|
||||
/* Track if DES H/W is available */
|
||||
static uint16_t crypto_des_avail = 1;
|
||||
/* Track if SHA H/W is available */
|
||||
static uint16_t crypto_sha_avail = 1;
|
||||
/* Track if ECC H/W is available */
|
||||
static uint16_t crypto_ecc_avail = 1;
|
||||
|
||||
/* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */
|
||||
static uint16_t crypto_init_counter = 0U;
|
||||
|
||||
static bool crypto_submodule_acquire(uint16_t *submodule_avail);
|
||||
static void crypto_submodule_release(uint16_t *submodule_avail);
|
||||
|
||||
/* Crypto done flags */
|
||||
#define CRYPTO_DONE_OK BIT0 /* Done with OK */
|
||||
#define CRYPTO_DONE_ERR BIT1 /* Done with error */
|
||||
|
||||
/* Track if PRNG H/W operation is done */
|
||||
static volatile uint16_t crypto_prng_done;
|
||||
/* Track if AES H/W operation is done */
|
||||
static volatile uint16_t crypto_aes_done;
|
||||
/* Track if DES H/W operation is done */
|
||||
static volatile uint16_t crypto_des_done;
|
||||
/* Track if ECC H/W operation is done */
|
||||
static volatile uint16_t crypto_ecc_done;
|
||||
|
||||
static void crypto_submodule_prestart(volatile uint16_t *submodule_done);
|
||||
static bool crypto_submodule_wait(volatile uint16_t *submodule_done);
|
||||
|
||||
/* As crypto init counter changes from 0 to 1:
|
||||
*
|
||||
* 1. Enable crypto clock
|
||||
* 2. Enable crypto interrupt
|
||||
*/
|
||||
void crypto_init(void)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (crypto_init_counter == USHRT_MAX) {
|
||||
core_util_critical_section_exit();
|
||||
error("Crypto clock enable counter would overflow (> USHRT_MAX)");
|
||||
}
|
||||
core_util_atomic_incr_u16(&crypto_init_counter, 1);
|
||||
if (crypto_init_counter == 1) {
|
||||
/* Enable IP clock
|
||||
*
|
||||
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
|
||||
*/
|
||||
CLK_EnableModuleClock_S(CRPT_MODULE);
|
||||
|
||||
NVIC_SetVector(CRPT_IRQn, (uint32_t) CRPT_IRQHandler);
|
||||
NVIC_EnableIRQ(CRPT_IRQn);
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
/* As crypto init counter changes from 1 to 0:
|
||||
*
|
||||
* 1. Disable crypto interrupt
|
||||
* 2. Disable crypto clock
|
||||
*/
|
||||
void crypto_uninit(void)
|
||||
{
|
||||
core_util_critical_section_enter();
|
||||
if (crypto_init_counter == 0) {
|
||||
core_util_critical_section_exit();
|
||||
error("Crypto clock enable counter would underflow (< 0)");
|
||||
}
|
||||
core_util_atomic_decr_u16(&crypto_init_counter, 1);
|
||||
if (crypto_init_counter == 0) {
|
||||
NVIC_DisableIRQ(CRPT_IRQn);
|
||||
|
||||
/* Enable IP clock
|
||||
*
|
||||
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
|
||||
*/
|
||||
CLK_DisableModuleClock_S(CRPT_MODULE);
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
}
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
void crypto_zeroize(void *v, size_t n)
|
||||
{
|
||||
volatile unsigned char *p = (volatile unsigned char*) v;
|
||||
while (n--) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
void crypto_zeroize32(uint32_t *v, size_t n)
|
||||
{
|
||||
volatile uint32_t *p = (volatile uint32_t*) v;
|
||||
while (n--) {
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool crypto_aes_acquire(void)
|
||||
{
|
||||
return crypto_submodule_acquire(&crypto_aes_avail);
|
||||
}
|
||||
|
||||
void crypto_aes_release(void)
|
||||
{
|
||||
crypto_submodule_release(&crypto_aes_avail);
|
||||
}
|
||||
|
||||
bool crypto_des_acquire(void)
|
||||
{
|
||||
return crypto_submodule_acquire(&crypto_des_avail);
|
||||
}
|
||||
|
||||
void crypto_des_release(void)
|
||||
{
|
||||
crypto_submodule_release(&crypto_des_avail);
|
||||
}
|
||||
|
||||
bool crypto_sha_acquire(void)
|
||||
{
|
||||
return crypto_submodule_acquire(&crypto_sha_avail);
|
||||
}
|
||||
|
||||
void crypto_sha_release(void)
|
||||
{
|
||||
crypto_submodule_release(&crypto_sha_avail);
|
||||
}
|
||||
|
||||
bool crypto_ecc_acquire(void)
|
||||
{
|
||||
return crypto_submodule_acquire(&crypto_ecc_avail);
|
||||
}
|
||||
|
||||
void crypto_ecc_release(void)
|
||||
{
|
||||
crypto_submodule_release(&crypto_ecc_avail);
|
||||
}
|
||||
|
||||
void crypto_prng_prestart(void)
|
||||
{
|
||||
crypto_submodule_prestart(&crypto_prng_done);
|
||||
}
|
||||
|
||||
bool crypto_prng_wait(void)
|
||||
{
|
||||
return crypto_submodule_wait(&crypto_prng_done);
|
||||
}
|
||||
|
||||
void crypto_aes_prestart(void)
|
||||
{
|
||||
crypto_submodule_prestart(&crypto_aes_done);
|
||||
}
|
||||
|
||||
bool crypto_aes_wait(void)
|
||||
{
|
||||
return crypto_submodule_wait(&crypto_aes_done);
|
||||
}
|
||||
|
||||
void crypto_des_prestart(void)
|
||||
{
|
||||
crypto_submodule_prestart(&crypto_des_done);
|
||||
}
|
||||
|
||||
bool crypto_des_wait(void)
|
||||
{
|
||||
return crypto_submodule_wait(&crypto_des_done);
|
||||
}
|
||||
|
||||
void crypto_ecc_prestart(void)
|
||||
{
|
||||
crypto_submodule_prestart(&crypto_ecc_done);
|
||||
}
|
||||
|
||||
bool crypto_ecc_wait(void)
|
||||
{
|
||||
return crypto_submodule_wait(&crypto_ecc_done);
|
||||
}
|
||||
|
||||
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
|
||||
{
|
||||
uint32_t buff_ = (uint32_t) buff;
|
||||
|
||||
return (((buff_ & 0x03) == 0) && /* Word-aligned buffer base address */
|
||||
((buff_size & (size_aligned_to - 1)) == 0) && /* Crypto submodule dependent buffer size alignment */
|
||||
(((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); /* 0x20000000-0x2FFFFFFF */
|
||||
}
|
||||
|
||||
/* Overlap cases
|
||||
*
|
||||
* 1. in_buff in front of out_buff:
|
||||
*
|
||||
* in in_end
|
||||
* | |
|
||||
* ||||||||||||||||
|
||||
* ||||||||||||||||
|
||||
* | |
|
||||
* out out_end
|
||||
*
|
||||
* 2. out_buff in front of in_buff:
|
||||
*
|
||||
* in in_end
|
||||
* | |
|
||||
* ||||||||||||||||
|
||||
* ||||||||||||||||
|
||||
* | |
|
||||
* out out_end
|
||||
*/
|
||||
bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size)
|
||||
{
|
||||
uint32_t in = (uint32_t) in_buff;
|
||||
uint32_t in_end = in + in_buff_size;
|
||||
uint32_t out = (uint32_t) out_buff;
|
||||
uint32_t out_end = out + out_buff_size;
|
||||
|
||||
bool overlap = (in <= out && out < in_end) || (out <= in && in < out_end);
|
||||
|
||||
return overlap;
|
||||
}
|
||||
|
||||
static bool crypto_submodule_acquire(uint16_t *submodule_avail)
|
||||
{
|
||||
uint16_t expectedCurrentValue = 1;
|
||||
return core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 0);
|
||||
}
|
||||
|
||||
static void crypto_submodule_release(uint16_t *submodule_avail)
|
||||
{
|
||||
uint16_t expectedCurrentValue = 0;
|
||||
while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1));
|
||||
}
|
||||
|
||||
static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
|
||||
{
|
||||
*submodule_done = 0;
|
||||
|
||||
/* Ensure memory accesses above are completed before DMA is started
|
||||
*
|
||||
* Replacing __DSB() with __DMB() is also OK in this case.
|
||||
*
|
||||
* Refer to "multi-master systems" section with DMA in:
|
||||
* https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf
|
||||
*/
|
||||
__DSB();
|
||||
}
|
||||
|
||||
static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
|
||||
{
|
||||
while (! *submodule_done);
|
||||
|
||||
/* Ensure while loop above and subsequent code are not reordered */
|
||||
__DSB();
|
||||
|
||||
if ((*submodule_done & CRYPTO_DONE_OK)) {
|
||||
/* Done with OK */
|
||||
return true;
|
||||
} else if ((*submodule_done & CRYPTO_DONE_ERR)) {
|
||||
/* Done with error */
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Crypto interrupt handler */
|
||||
void CRPT_IRQHandler()
|
||||
{
|
||||
uint32_t intsts;
|
||||
|
||||
if ((intsts = PRNG_GET_INT_FLAG(CRYPTO_MODBASE())) != 0) {
|
||||
/* Done with OK */
|
||||
crypto_prng_done |= CRYPTO_DONE_OK;
|
||||
/* Clear interrupt flag */
|
||||
PRNG_CLR_INT_FLAG(CRYPTO_MODBASE());
|
||||
} else if ((intsts = AES_GET_INT_FLAG(CRYPTO_MODBASE())) != 0) {
|
||||
/* Done with OK */
|
||||
crypto_aes_done |= CRYPTO_DONE_OK;
|
||||
/* Clear interrupt flag */
|
||||
AES_CLR_INT_FLAG(CRYPTO_MODBASE());
|
||||
} else if ((intsts = TDES_GET_INT_FLAG(CRYPTO_MODBASE())) != 0) {
|
||||
/* Done with OK */
|
||||
crypto_des_done |= CRYPTO_DONE_OK;
|
||||
/* Clear interrupt flag */
|
||||
TDES_CLR_INT_FLAG(CRYPTO_MODBASE());
|
||||
} else if ((intsts = ECC_GET_INT_FLAG(CRYPTO_MODBASE())) != 0) {
|
||||
/* Check interrupt flags */
|
||||
if (intsts & CRPT_INTSTS_ECCIF_Msk) {
|
||||
/* Done with OK */
|
||||
crypto_ecc_done |= CRYPTO_DONE_OK;
|
||||
} else if (intsts & CRPT_INTSTS_ECCEIF_Msk) {
|
||||
/* Done with error */
|
||||
crypto_ecc_done |= CRYPTO_DONE_ERR;
|
||||
}
|
||||
/* Clear interrupt flag */
|
||||
ECC_CLR_INT_FLAG(CRYPTO_MODBASE());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2018 Nuvoton
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_CRYPTO_MISC_H
|
||||
#define MBED_CRYPTO_MISC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "partition_M2351.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Get Crypto module base dependent on security state */
|
||||
__STATIC_INLINE CRPT_T *CRYPTO_MODBASE(void)
|
||||
{
|
||||
#if defined(SCU_INIT_PNSSET1_VAL) && (SCU_INIT_PNSSET1_VAL & (1<<18))
|
||||
return CRPT_NS;
|
||||
#else
|
||||
return CRPT;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Init/Uninit crypto module */
|
||||
void crypto_init(void);
|
||||
void crypto_uninit(void);
|
||||
|
||||
/* Clear buffer to zero
|
||||
* Implementation that should never be optimized out by the compiler */
|
||||
void crypto_zeroize(void *v, size_t n);
|
||||
void crypto_zeroize32(uint32_t *v, size_t n);
|
||||
|
||||
/* Acquire/release ownership of AES H/W */
|
||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
|
||||
bool crypto_aes_acquire(void);
|
||||
void crypto_aes_release(void);
|
||||
|
||||
/* Acquire/release ownership of DES H/W */
|
||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
|
||||
bool crypto_des_acquire(void);
|
||||
void crypto_des_release(void);
|
||||
|
||||
/* Acquire/release ownership of SHA H/W */
|
||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
|
||||
bool crypto_sha_acquire(void);
|
||||
void crypto_sha_release(void);
|
||||
|
||||
/* Acquire/release ownership of ECC H/W */
|
||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
|
||||
bool crypto_ecc_acquire(void);
|
||||
void crypto_ecc_release(void);
|
||||
|
||||
/* Flow control between crypto/xxx start and crypto/xxx ISR
|
||||
*
|
||||
* crypto_xxx_prestart/crypto_xxx_wait encapsulate control flow between crypto/xxx start and crypto/xxx ISR.
|
||||
*
|
||||
* crypto_xxx_prestart will also address synchronization issue with memory barrier instruction.
|
||||
*
|
||||
* On finish, return of crypto_xxx_wait indicates success or not:
|
||||
* true if successful
|
||||
* false if failed
|
||||
*
|
||||
* Example: Start AES H/W and wait for its finish
|
||||
* crypto_aes_prestart();
|
||||
* AES_Start();
|
||||
* crypto_aes_wait();
|
||||
*/
|
||||
void crypto_prng_prestart(void);
|
||||
bool crypto_prng_wait(void);
|
||||
void crypto_aes_prestart(void);
|
||||
bool crypto_aes_wait(void);
|
||||
void crypto_des_prestart(void);
|
||||
bool crypto_des_wait(void);
|
||||
void crypto_ecc_prestart(void);
|
||||
bool crypto_ecc_wait(void);
|
||||
|
||||
|
||||
/* Check if buffer can be used for crypto DMA. It has the following requirements:
|
||||
* (1) Word-aligned buffer base address
|
||||
* (2) Crypto submodule (AES, DES, SHA, etc.) dependent buffer size alignment. Must be 2 power.
|
||||
* (3) Located in 0x20000000-0x2FFFFFFF region
|
||||
*/
|
||||
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to);
|
||||
|
||||
/* Check if input/output buffers are overlapped */
|
||||
bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -164,7 +164,7 @@ __STATIC_INLINE void FMC_NSBA_Setup(void)
|
|||
// <o.17> CRC <0=> Secure <1=> Non-Secure
|
||||
// <o.18> CRPT <0=> Secure <1=> Non-Secure
|
||||
*/
|
||||
#define SCU_INIT_PNSSET1_VAL 0xFFFBFFFF
|
||||
#define SCU_INIT_PNSSET1_VAL 0xFFFFFFFF
|
||||
/*
|
||||
PNSSET2
|
||||
*/
|
||||
|
@ -718,7 +718,7 @@ __STATIC_INLINE void SCU_Setup(void)
|
|||
|
||||
//
|
||||
*/
|
||||
#define NVIC_INIT_ITNS2_VAL 0xFFFFFF7F
|
||||
#define NVIC_INIT_ITNS2_VAL 0xFFFFFFFF
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-2018 Nuvoton
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if DEVICE_TRNG
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cmsis.h"
|
||||
#include "us_ticker_api.h"
|
||||
#include "trng_api.h"
|
||||
#include "crypto-misc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Get Random number generator.
|
||||
*/
|
||||
|
||||
#define PRNG_KEY_SIZE (0x20UL)
|
||||
|
||||
static void trng_get(unsigned char *pConversionData)
|
||||
{
|
||||
uint32_t *p32ConversionData;
|
||||
|
||||
p32ConversionData = (uint32_t *)pConversionData;
|
||||
|
||||
PRNG_Open(CRYPTO_MODBASE(), PRNG_KEY_SIZE_256, 1, us_ticker_read());
|
||||
crypto_prng_prestart();
|
||||
PRNG_Start(CRYPTO_MODBASE());
|
||||
crypto_prng_wait();
|
||||
|
||||
PRNG_Read(CRYPTO_MODBASE(), p32ConversionData);
|
||||
}
|
||||
|
||||
void trng_init(trng_t *obj)
|
||||
{
|
||||
(void)obj;
|
||||
|
||||
/* Init crypto module */
|
||||
crypto_init();
|
||||
|
||||
PRNG_ENABLE_INT(CRYPTO_MODBASE());
|
||||
}
|
||||
|
||||
void trng_free(trng_t *obj)
|
||||
{
|
||||
(void)obj;
|
||||
|
||||
PRNG_DISABLE_INT(CRYPTO_MODBASE());
|
||||
|
||||
/* Uninit crypto module */
|
||||
crypto_uninit();
|
||||
}
|
||||
|
||||
int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)
|
||||
{
|
||||
(void)obj;
|
||||
unsigned char tmpBuff[PRNG_KEY_SIZE];
|
||||
size_t cur_length = 0;
|
||||
|
||||
while (length >= sizeof(tmpBuff)) {
|
||||
trng_get(output);
|
||||
output += sizeof(tmpBuff);
|
||||
cur_length += sizeof(tmpBuff);
|
||||
length -= sizeof(tmpBuff);
|
||||
}
|
||||
if (length > 0) {
|
||||
trng_get(tmpBuff);
|
||||
memcpy(output, tmpBuff, length);
|
||||
cur_length += length;
|
||||
crypto_zeroize(tmpBuff, sizeof(tmpBuff));
|
||||
}
|
||||
*output_length = cur_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -4298,7 +4298,7 @@
|
|||
"is_disk_virtual": true,
|
||||
"supported_toolchains": ["GCC_ARM", "IAR", "ARMC6"],
|
||||
"inherits": ["Target"],
|
||||
"device_has": ["I2C", "I2CSLAVE", "I2C_ASYNCH", "LOWPOWERTIMER", "RTC", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "FLASH"],
|
||||
"device_has": ["I2C", "I2CSLAVE", "I2C_ASYNCH", "LOWPOWERTIMER", "RTC", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "STDIO_MESSAGES", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "TRNG", "FLASH"],
|
||||
"detect_code": ["1305"],
|
||||
"release_versions": ["5"],
|
||||
"device_name": "M2351KIAAEES",
|
||||
|
@ -4306,7 +4306,8 @@
|
|||
},
|
||||
"NUMAKER_PFM_M2351_S": {
|
||||
"core": "Cortex-M23",
|
||||
"inherits": ["NUMAKER_PFM_M2351"]
|
||||
"inherits": ["NUMAKER_PFM_M2351"],
|
||||
"device_has_remove": ["TRNG"]
|
||||
},
|
||||
"NUMAKER_PFM_M2351_NS": {
|
||||
"core": "Cortex-M23-NS",
|
||||
|
|
Loading…
Reference in New Issue