[NUC472/M487] Refine flow control code between crypto start and crypto ISR

pull/4925/head
ccli8 2017-12-15 13:49:51 +08:00
parent e1fbf0f6a7
commit 0c1098483f
8 changed files with 153 additions and 52 deletions

View File

@ -176,17 +176,9 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize);
g_AES_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();
crypto_aes_prestart();
AES_Start(0, CRYPTO_DMA_ONE_SHOT);
while (!g_AES_done);
crypto_aes_wait();
if( pOut != output ) {
memcpy(output, au8OutputData, dataSize);

View File

@ -176,17 +176,9 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx,
AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize);
g_AES_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();
crypto_aes_prestart();
AES_Start(0, CRYPTO_DMA_ONE_SHOT);
while (!g_AES_done);
crypto_aes_wait();
if( pOut != output ) {
memcpy(output, au8OutputData, dataSize);

View File

@ -24,9 +24,6 @@
#include "nu_bitutil.h"
#include "crypto-misc.h"
volatile int g_PRNG_done;
volatile int g_AES_done;
/* Track if AES H/W is available */
static uint16_t crypto_aes_avail = 1;
/* Track if DES H/W is available */
@ -40,6 +37,14 @@ 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);
/* 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;
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
@ -125,6 +130,26 @@ void crypto_sha_release(void)
crypto_submodule_release(&crypto_sha_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);
}
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
{
uint32_t buff_ = (uint32_t) buff;
@ -146,14 +171,35 @@ static void crypto_submodule_release(uint16_t *submodule_avail)
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);
return true;
}
/* Crypto interrupt handler */
void CRYPTO_IRQHandler()
{
if (PRNG_GET_INT_FLAG()) {
g_PRNG_done = 1;
crypto_prng_done = 1;
PRNG_CLR_INT_FLAG();
} else if (AES_GET_INT_FLAG()) {
g_AES_done = 1;
crypto_aes_done = 1;
AES_CLR_INT_FLAG();
}
}

View File

@ -23,14 +23,6 @@
extern "C" {
#endif
/* Flags to indicate crypto H/W operation has done
*
* Crypto driver would clear it before trigger and wait for it.
* Crypto interrupt handler would set it on done or error.
*/
extern volatile int g_PRNG_done;
extern volatile int g_AES_done;
/* Init/Uninit crypto module */
void crypto_init(void);
void crypto_uninit(void);
@ -54,6 +46,27 @@ void crypto_des_release(void);
bool crypto_sha_acquire(void);
void crypto_sha_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);
/* 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.

View File

@ -36,8 +36,9 @@ static void trng_get(unsigned char *pConversionData)
p32ConversionData = (uint32_t *)pConversionData;
PRNG_Open(PRNG_KEY_SIZE_256, 1, us_ticker_read());
crypto_prng_prestart();
PRNG_Start();
while (!g_PRNG_done);
crypto_prng_wait();
PRNG_Read(p32ConversionData);
}
@ -85,4 +86,3 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l
}
#endif

View File

@ -24,9 +24,6 @@
#include "nu_bitutil.h"
#include "crypto-misc.h"
volatile int g_PRNG_done;
volatile int g_AES_done;
/* Track if AES H/W is available */
static uint16_t crypto_aes_avail = 1;
/* Track if DES H/W is available */
@ -40,6 +37,14 @@ 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);
/* 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;
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
@ -125,6 +130,26 @@ void crypto_sha_release(void)
crypto_submodule_release(&crypto_sha_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);
}
bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
{
uint32_t buff_ = (uint32_t) buff;
@ -146,14 +171,35 @@ static void crypto_submodule_release(uint16_t *submodule_avail)
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);
return true;
}
/* Crypto interrupt handler */
void CRYPTO_IRQHandler()
{
if (PRNG_GET_INT_FLAG()) {
g_PRNG_done = 1;
crypto_prng_done = 1;
PRNG_CLR_INT_FLAG();
} else if (AES_GET_INT_FLAG()) {
g_AES_done = 1;
crypto_aes_done = 1;
AES_CLR_INT_FLAG();
}
}

View File

@ -23,14 +23,6 @@
extern "C" {
#endif
/* Flags to indicate crypto H/W operation has done
*
* Crypto driver would clear it before trigger and wait for it.
* Crypto interrupt handler would set it on done or error.
*/
extern volatile int g_PRNG_done;
extern volatile int g_AES_done;
/* Init/Uninit crypto module */
void crypto_init(void);
void crypto_uninit(void);
@ -54,6 +46,27 @@ void crypto_des_release(void);
bool crypto_sha_acquire(void);
void crypto_sha_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);
/* 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.

View File

@ -23,7 +23,6 @@
#include <stdlib.h>
#include <string.h>
#include "cmsis.h"
#include "NUC472_442.h"
#include "us_ticker_api.h"
#include "trng_api.h"
#include "crypto-misc.h"
@ -41,8 +40,9 @@ static void trng_get(unsigned char *pConversionData)
p32ConversionData = (uint32_t *)pConversionData;
PRNG_Open(PRNG_KEY_SIZE_256, 1, us_ticker_read());
crypto_prng_prestart();
PRNG_Start();
while (!g_PRNG_done);
crypto_prng_wait();
PRNG_Read(p32ConversionData);
}
@ -88,6 +88,5 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l
*output_length = cur_length;
return 0;
}
#endif
#endif