Skip to content

arch/arm/stm32h5: Add CRC header - #19928

Merged
xiaoxiang781216 merged 2 commits into
apache:masterfrom
liam-geotab:stm32h5-crc
Aug 23, 2026
Merged

arch/arm/stm32h5: Add CRC header#19928
xiaoxiang781216 merged 2 commits into
apache:masterfrom
liam-geotab:stm32h5-crc

Conversation

@liam-geotab

Copy link
Copy Markdown
Contributor

Summary

Add CRC header based on arch/arm/src/common/stm32/hardware/stm32_crc.h and select STM32_HAVE_CRC in Kconfig.

CRC_IDR_MASK widened from 0xFF to 0xFFFFFFFF.

Impact

As usual, drivers must include this "hardware/" header explicitly and manipulate the registers.

Now that stm32h5 defines STM32_HAVE_CRC, STM32_CRC can be enabled, which causes the clock to be enabled in rcc_enableahb1().

Testing

I validated by copying the H7 crypto driver implementation and removing everything except crc32 so that the crypto crc32 test cases could run on H5 using the H5 CRC definitions.

nucleo-h563zi:nsh with:

CONFIG_ALLOW_BSD_COMPONENTS=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_CRYPTODEV=y
CONFIG_CRYPTO_CRYPTODEV_HARDWARE=y
CONFIG_STM32_CRC=y
CONFIG_TESTING_CRYPTO=y
CONFIG_TESTING_CRYPTO_CRC32=y
nsh> crc32
crc32 test case 1 success
crc32 test case 2 success
crc32 test case 3 success
crc32 test case 4 success
crc32 test case 5 success
crc32 test case 6 success
crc32 test case 7 success
crc32 test case 8 success
diff --git a/arch/arm/src/stm32h5/Make.defs b/arch/arm/src/stm32h5/Make.defs
index 7d35a2b939..6ca3dfe323 100644
--- a/arch/arm/src/stm32h5/Make.defs
+++ b/arch/arm/src/stm32h5/Make.defs
@@ -116,6 +116,8 @@ ifeq ($(CONFIG_STM32_IWDG),y)
 CHIP_CSRCS += stm32_iwdg.c
 endif
 
+CHIP_CSRCS += stm32_crypto.c
+
 # Required chip type specific files
 
 ifeq ($(CONFIG_STM32_STM32H5XXXX),y)
diff --git a/arch/arm/src/stm32h7/stm32_crypto.c b/arch/arm/src/stm32h5/stm32_crypto.c
index c0c7bfb55d..f20596aa02 100644
--- a/arch/arm/src/stm32h7/stm32_crypto.c
+++ b/arch/arm/src/stm32h5/stm32_crypto.c
@@ -35,9 +35,33 @@
 #include <nuttx/crypto/crypto.h>
 
 #include "arm_internal.h"
-#include "hardware/stm32h7x3xx_rcc.h"
-#include "hardware/stm32h7xxxx_crc.h"
-#include "hardware/stm32h7xxxx_hash.h"
+#include "hardware/stm32h5xxx_rcc.h"
+#include "hardware/stm32_crc.h"
+
+/* CRC register offsets *****************************************************/
+
+/* CRC register addresses ***************************************************/
+
+/* CRC register bit definitions *********************************************/
+
+/* CRC CR register */
+
+#define CRC_CR_REVOUT_SHIFT       7
+#define CRC_CR_REV_OUT_MASK       CRC_CR_REVOUT
+#define CRC_CR_REV_OUT_NONE       (0 << CRC_CR_REVOUT_SHIFT)
+#define CRC_CR_REV_OUT            CRC_CR_REVOUT
+#define CRC_CR_REV_IN_SHIFT       CRC_CR_REVIN_SHIFT
+#define CRC_CR_REV_IN_MASK        CRC_CR_REVIN_MASK
+#define CRC_CR_REV_IN_NONE        CRC_CR_REVIN_NONE
+#define CRC_CR_REV_IN_BYTE        CRC_CR_REVIN_BYTE
+#define CRC_CR_REV_IN_HALFWORD    CRC_CR_REVIN_HWORD
+#define CRC_CR_REV_IN_WORD        CRC_CR_REVIN_WORD
+
+#define CRC_CR_POLYSIZE_32BIT     CRC_CR_POLYSIZE_32
+#define CRC_CR_POLYSIZE_16BIT     CRC_CR_POLYSIZE_16
+#define CRC_CR_POLYSIZE_8BIT      CRC_CR_POLYSIZE_8
+#define CRC_CR_POLYSIZE_7BIT      CRC_CR_POLYSIZE_7
+#define CRC_CR_RESET_SHIFT        0
 
 /* Following constants used in reverse32() to reverse
  * bit order of 32-bit value
@@ -413,11 +437,11 @@ static int crc32_init(struct stm32_crypto_data *sw)
 
       /* Clear/set AHB4RSTR to reset CRC peripheral */
 
-      regval  = stm32crypto_getreg32(STM32_RCC_AHB4RSTR);
-      regval |= RCC_AHB4RSTR_CRCRST;
-      stm32crypto_putreg32(regval, STM32_RCC_AHB4RSTR);
-      regval &= ~RCC_AHB4RSTR_CRCRST;
-      stm32crypto_putreg32(regval, STM32_RCC_AHB4RSTR);
+      regval  = stm32crypto_getreg32(STM32_RCC_AHB1RSTR);
+      regval |= RCC_AHB1RSTR_CRCRST;
+      stm32crypto_putreg32(regval, STM32_RCC_AHB1RSTR);
+      regval &= ~RCC_AHB1RSTR_CRCRST;
+      stm32crypto_putreg32(regval, STM32_RCC_AHB1RSTR);
 
       leave_critical_section(flags);
     }
@@ -504,250 +528,6 @@ static int crc32_final(struct stm32_crypto_data *sw, caddr_t digest)
   return 0;
 }
 
-static int hash_init(struct stm32_crypto_data *sw)
-{
-  irqstate_t flags;
-  uint32_t regval;
-
-  stm32cryptoinfo("");
-
-  if (!g_stm32_hash_initialized)
-    {
-      g_stm32_hash_initialized = true;
-
-      flags = enter_critical_section();
-
-      /* Clear/set AHB2RSTR to reset CRYP peripheral */
-
-      regval  = stm32crypto_getreg32(STM32_RCC_AHB2RSTR);
-      regval |= RCC_AHB2RSTR_HASHRST;
-      stm32crypto_putreg32(regval, STM32_RCC_AHB2RSTR);
-      regval &= ~RCC_AHB2RSTR_HASHRST;
-      stm32crypto_putreg32(regval, STM32_RCC_AHB2RSTR);
-
-      leave_critical_section(flags);
-    }
-
-  /* Set the algorithm and digest size */
-
-  regval = 0;
-  switch (sw->hw_alg)
-    {
-      case CRYPTO_SHA1:
-      case CRYPTO_SHA1_HMAC:
-        regval = HASH_CR_ALGO_SHA1;
-        sw->u.hash.dsize = 20;
-        break;
-      case CRYPTO_MD5:
-      case CRYPTO_MD5_HMAC:
-        regval = HASH_CR_ALGO_MD5;
-        sw->u.hash.dsize = 16;
-        break;
-      case CRYPTO_SHA2_224:
-      case CRYPTO_SHA2_224_HMAC:
-        regval = HASH_CR_ALGO_SHA2_224;
-        sw->u.hash.dsize = 28;
-      break;
-      case CRYPTO_SHA2_256:
-      case CRYPTO_SHA2_256_HMAC:
-        regval = HASH_CR_ALGO_SHA2_256;
-        sw->u.hash.dsize = 32;
-        break;
-
-      default:
-        return -EINVAL;
-    }
-
-  /* If HMAC set mode, and key is large set HASH_CR_LKEY bit */
-
-  if (sw->u.hash.hmac)
-  {
-    regval |= HASH_CR_MODE_HMAC;
-    stm32cryptoinfo("klen %" PRIx32 "", sw->u.hash.klen);
-    if (sw->u.hash.klen > 64)
-    {
-      regval |= HASH_CR_LKEY_GT_64;
-    }
-  }
-
-  regval |= HASH_CR_INIT;       /* set init to configure HASH algorithm */
-  regval |= HASH_CR_DATATYPE_8; /* 8-bit data... */
-  stm32crypto_putreg32(regval, STM32_HASH_CR);
-
-  sw->u.hash.rlen = 0;
-  sw->u.hash.rdata = 0;
-
-  return 0;
-}
-
-static int hash_update(struct stm32_crypto_data *sw,
-                       uint8_t *buf, uint32_t len)
-{
-  const uint8_t *in_byte = buf;
-  const uint32_t *in_block;
-  int ret;
-
-  stm32cryptoinfo("buf %" PRIxPTR " len %" PRIu32 "",
-                  (uintptr_t)buf, len);
-
-  if (len == 0)
-    {
-      return 0;
-    }
-
-  /* If any remainder leftover from previous accumulation
-   * then accumulate them into hash.rdata to
-   * push into DIN
-   */
-
-  if (sw->u.hash.rlen)
-    {
-      while (sw->u.hash.rlen < sizeof(uint32_t))
-        {
-          if (!len)
-            {
-              break;
-            }
-
-          sw->u.hash.rdata |= (in_byte[0] << (8 * sw->u.hash.rlen));
-          in_byte++;
-          sw->u.hash.rlen++;
-          len--;
-        }
-
-      /* If hash_rlen still not sizeof(uint32_t) then input buffer
-       * doesn't hold enough bytes to write into DIN.
-       */
-
-      if (sw->u.hash.rlen < sizeof(uint32_t))
-        {
-          return 0;
-        }
-
-      stm32crypto_putreg32(sw->u.hash.rdata, STM32_HASH_DIN);
-      sw->u.hash.rlen = 0;
-      sw->u.hash.rdata = 0x0;
-    }
-
-  in_block = (uint32_t *)in_byte;
-
-  /* Loop pushing uint32_t of hash data into HASH_DIN */
-
-  while (len >= sizeof(uint32_t))
-    {
-      ret = stm32_wait_for_clr(STM32_HASH_SR, HASH_SR_BUSY,
-                             STM32H7_HASH_TIMEOUT);
-      if (ret < 0)
-        {
-          return ret;
-        }
-
-      stm32crypto_putreg32(*in_block, STM32_HASH_DIN);
-      in_block++;
-      len -= sizeof(uint32_t);
-    }
-
-  /* Accumulate any remaining bytes into hash.rdata */
-
-  if (len)
-    {
-      stm32cryptoinfo("len %" PRIu32 " hash.rlen: %" PRIu32 "",
-                      len, sw->u.hash.rlen);
-      in_byte = (uint8_t *)in_block;
-      while (len)
-        {
-          sw->u.hash.rdata |= (in_byte[0] << (8 * sw->u.hash.rlen));
-          sw->u.hash.rlen++;
-          in_byte++;
-          len--;
-        }
-    }
-
-  return 0;
-}
-
-static int hash_final(struct stm32_crypto_data *sw, caddr_t digest,
-                      uint32_t wait_flag)
-{
-  uint32_t *out = (uint32_t *)digest;
-  uint32_t regval;
-  int ret;
-
-  stm32cryptoinfo("digest %" PRIxPTR "", (uintptr_t)digest);
-
-  /* If any data left in rdata, write it out */
-
-  if (sw->u.hash.rlen)
-    {
-      stm32crypto_putreg32(sw->u.hash.rdata, STM32_HASH_DIN);
-    }
-
-  /* Start digest calculation. Set NBLW to number of
-   * bits of valid data in last write to HASH_DIN, and
-   * set DCAL to start the digest calculation.
-   */
-
-  regval = HASH_STR_NBLW_BYTES((uint32_t)sw->u.hash.rlen);
-  stm32crypto_putreg32(regval, STM32_HASH_STR);
-
-  /* Set DCAL _after_ setting NBLW; have seen incorrect HMAC hash
-   * result if both done at same time.
-   */
-
-  regval |= HASH_STR_DCAL;
-  stm32crypto_putreg32(regval, STM32_HASH_STR);
-
-  sw->u.hash.rlen = 0;
-  sw->u.hash.rdata = 0x0;
-
-  /* Wait for the digest to compute
-   * (for HMAC wait for data to be ready)
-   */
-
-  ret = stm32_wait_for_set(STM32_HASH_SR, wait_flag,
-                           STM32H7_HASH_TIMEOUT);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
-  /* Extract the resultant hash (if desired) */
-
-  if (digest)
-    {
-      regval = stm32crypto_getreg32(STM32_HASH_HRA0);
-      *out++ = __builtin_bswap32(regval);
-      regval = stm32crypto_getreg32(STM32_HASH_HRA1);
-      *out++ = __builtin_bswap32(regval);
-      regval = stm32crypto_getreg32(STM32_HASH_HRA2);
-      *out++ = __builtin_bswap32(regval);
-      regval = stm32crypto_getreg32(STM32_HASH_HRA3);
-      *out++ = __builtin_bswap32(regval);
-
-      if (sw->u.hash.dsize >= 20)
-        {
-          regval = stm32crypto_getreg32(STM32_HASH_HRA4);
-          *out++ = __builtin_bswap32(regval);
-        }
-
-      if (sw->u.hash.dsize >= 28)
-        {
-          regval = stm32crypto_getreg32(STM32_HASH_HR5);
-          *out++ = __builtin_bswap32(regval);
-          regval = stm32crypto_getreg32(STM32_HASH_HR6);
-          *out++ = __builtin_bswap32(regval);
-        }
-
-      if (sw->u.hash.dsize == 32)
-        {
-          regval = stm32crypto_getreg32(STM32_HASH_HR7);
-          *out++ = __builtin_bswap32(regval);
-        }
-    }
-
-  return 0;
-}
-
 /****************************************************************************
  * Name: stm32_freesession
  *
@@ -781,24 +561,7 @@ static int stm32_freesession(uint64_t tid)
 
       switch (sw->hw_alg)
         {
-          case CRYPTO_SHA1_HMAC:
-          case CRYPTO_MD5_HMAC:
-          case CRYPTO_SHA2_224_HMAC:
-          case CRYPTO_SHA2_256_HMAC:
-            if (sw->u.hash.key)
-            {
-              explicit_bzero(sw->u.hash.key, sw->u.hash.klen);
-              kmm_free(sw->u.hash.key);
-            }
-            break;
-
           case CRYPTO_CRC32:
-          case CRYPTO_SHA1:
-          case CRYPTO_MD5:
-          case CRYPTO_SHA2_224:
-          case CRYPTO_SHA2_256:
-          case CRYPTO_AES_CBC:
-          case CRYPTO_AES_CTR:
             break;
 
           default:
@@ -903,75 +666,10 @@ static int stm32_newsession(uint32_t *sid, struct cryptoini *cri)
       sw->hw_alg = cri->cri_alg;
       switch (cri->cri_alg)
         {
-          case CRYPTO_MD5_HMAC:
-          case CRYPTO_SHA1_HMAC:
-          case CRYPTO_SHA2_224_HMAC:
-          case CRYPTO_SHA2_256_HMAC:
-            sw->u.hash.hmac = true;
-            sw->u.hash.klen = cri->cri_klen / 8;
-            sw->u.hash.key = kmm_malloc(sw->u.hash.klen);
-            if (sw->u.hash.key == NULL)
-            {
-              return -ENOBUFS;
-            }
-
-            bcopy(cri->cri_key, sw->u.hash.key, sw->u.hash.klen);
-
-            /* Initialize HW, push the key into DIN, wait for DINIS */
-
-            ret = hash_init(sw);
-            if (ret < 0)
-              {
-                return ret;
-              }
-
-            stm32cryptoinfo("Push %" PRIu32 " bytes of outer hash into DIN",
-                           sw->u.hash.klen);
-            ret = hash_update(sw, sw->u.hash.key, sw->u.hash.klen);
-            if (ret < 0)
-              {
-                return ret;
-              }
-
-            stm32cryptoinfo("Wait for DINIS");
-            ret = hash_final(sw, NULL, HASH_SR_DINIS);
-            if (ret < 0)
-              {
-                return ret;
-              }
-
-            break;
-
-          case CRYPTO_MD5:
-          case CRYPTO_SHA1:
-          case CRYPTO_SHA2_224:
-          case CRYPTO_SHA2_256:
-            sw->u.hash.hmac = false;
-            ret = hash_init(sw);
-            if (ret < 0)
-            {
-              return ret;
-            }
-            break;
-
           case CRYPTO_CRC32:
             crc32_init(sw);
             break;
 
-          case CRYPTO_AES_CBC:
-            break;
-
-          case CRYPTO_AES_CTR:
-            klen = cri->cri_klen / 8 - 4;
-            if ((klen != 16) && (klen != 24) && (klen != 32))
-            {
-              /* stm32h7 aes-ctr key bits support 128, 192, or 256 */
-
-              return -EINVAL;
-            }
-
-            break;
-
           default:
             stm32_freesession(i);
             return -EINVAL;
@@ -1054,58 +752,6 @@ static int stm32_process(struct cryptop *crp)
 
       switch (crd->crd_alg)
         {
-          case CRYPTO_MD5:
-          case CRYPTO_SHA1:
-          case CRYPTO_SHA2_224:
-          case CRYPTO_SHA2_256:
-            if (crd->crd_flags & CRD_F_UPDATE)
-              {
-                return hash_update(sw, crp->crp_buf, crd->crd_len);
-              }
-            else
-              {
-                return hash_final(sw, crp->crp_mac, HASH_SR_DCIS);
-              }
-            break;
-          case CRYPTO_MD5_HMAC:
-          case CRYPTO_SHA1_HMAC:
-          case CRYPTO_SHA2_224_HMAC:
-          case CRYPTO_SHA2_256_HMAC:
-            ret = hash_update(sw, crp->crp_buf, crd->crd_len);
-            if (ret < 0 || (crd->crd_flags & CRD_F_UPDATE))
-              {
-                return ret;
-              }
-
-            /* All HMAC data has been hashed, next step is
-             * 1) set DCAL and HBLW, wait for DINIS
-             */
-
-            ret = hash_final(sw, NULL, HASH_SR_DINIS);
-            if (ret < 0)
-              {
-                stm32cryptoinfo("");
-                return ret;
-              }
-
-            /* 2) Push outer hash (same as inner hash) into DIN */
-
-            stm32cryptoinfo("Push %" PRIu32 " bytes of inner hash",
-                            sw->u.hash.klen);
-
-            ret = hash_update(sw, sw->u.hash.key, sw->u.hash.klen);
-            if (ret < 0)
-              {
-                stm32cryptoinfo("");
-                return ret;
-              }
-
-            /* 3) normal finalization */
-
-            return hash_final(sw, crp->crp_mac, HASH_SR_DCIS);
-
-            break;
-
           case CRYPTO_CRC32:
             if (crd->crd_flags & CRD_F_UPDATE)
             {
@@ -1116,22 +762,6 @@ static int stm32_process(struct cryptop *crp)
               return crc32_final(sw, crp->crp_mac);
             }
             break;
-          case CRYPTO_AES_CBC:
-            return aes_cypher(crp->crp_dst, crp->crp_buf, crd->crd_len,
-                              crp->crp_iv, crd->crd_key, 16,
-                              AES_MODE_CBC, crd->crd_flags & CRD_F_ENCRYPT);
-          case CRYPTO_AES_CTR:
-
-            memcpy(iv, crd->crd_key + crd->crd_klen / 8 - AESCTR_NONCESIZE,
-                   AESCTR_NONCESIZE);
-            memcpy(iv + AESCTR_NONCESIZE, crp->crp_iv, AESCTR_IVSIZE);
-            memcpy(iv + AESCTR_NONCESIZE + AESCTR_IVSIZE,
-                   (uint8_t *)crp->crp_iv + AESCTR_IVSIZE, 4);
-
-            return aes_cypher(crp->crp_dst, crp->crp_buf,
-                              crd->crd_len, iv, crd->crd_key,
-                              crd->crd_klen / 8 - AESCTR_NONCESIZE,
-                              AES_MODE_CTR, crd->crd_flags & CRD_F_ENCRYPT);
           default:
             stm32cryptoinfo("crc_alg %d", crd->crd_alg);
             return -EINVAL;
@@ -1161,18 +791,6 @@ void hwcr_init(void)
   memset(algs, 0, sizeof(algs));
 
   algs[CRYPTO_CRC32] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_MD5] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA1] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA2_224] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA2_256] = CRYPTO_ALG_FLAG_SUPPORTED;
-
-  algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA2_224_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_SHA2_256_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
-
-  algs[CRYPTO_AES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
-  algs[CRYPTO_AES_CTR] = CRYPTO_ALG_FLAG_SUPPORTED;
 
   crypto_register(hwcr_id, algs, stm32_newsession,
                   stm32_freesession, stm32_process);

EdwardLo-WNC and others added 2 commits August 21, 2026 16:32
Add CRC header based on arch/arm/src/common/stm32/hardware/stm32_crc.h
and select STM32_HAVE_CRC in Kconfig

Signed-off-by: Liam Howatt <liamhowatt@geotab.com>
STM32H5 has hardware CRC support and the header
file is present.

Signed-off-by: Liam Howatt <liamhowatt@geotab.com>
@github-actions github-actions Bot added Area: Documentation Improvements or additions to documentation Arch: arm Issues related to ARM (32-bit) architecture Size: S The size of the change in this PR is small labels Aug 21, 2026
@github-actions

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@xiaoxiang781216
xiaoxiang781216 merged commit 88251df into apache:master Aug 23, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Area: Documentation Improvements or additions to documentation Size: S The size of the change in this PR is small

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants