@@ -435,50 +435,93 @@ void hal_prepare_boot(void)
435435
436436#ifdef FLASH_OTP_KEYSTORE
437437
438+ #define FLASH_OTP_BLOCK_SIZE (64)
439+
438440/* Public API */
439441
442+ int hal_flash_otp_set_readonly (uint32_t flashAddress , uint16_t length )
443+ {
444+ uint32_t start_block = (flashAddress - FLASH_OTP_BASE ) / FLASH_OTP_BLOCK_SIZE ;
445+ uint32_t count = length / FLASH_OTP_BLOCK_SIZE ;
446+ uint32_t bmap = 0 ;
447+ unsigned int i ;
448+ if (start_block + count > 32 )
449+ return -1 ;
450+
451+ if ((length % FLASH_OTP_BLOCK_SIZE ) != 0 )
452+ {
453+ count ++ ;
454+ }
455+
456+ /* Turn on the bits */
457+ for (i = start_block ; i < (start_block + count ); i ++ ) {
458+ bmap |= (1 << i );
459+ }
460+ /* Enable OTP write protection for the selected blocks */
461+ while ((bmap & FLASH_OTPBLR_CUR ) != bmap ) {
462+ FLASH_OTPBLR_PRG |= bmap ;
463+ ISB ();
464+ DSB ();
465+ }
466+ return 0 ;
467+ }
468+
440469int hal_flash_otp_write (uint32_t flashAddress , const void * data , uint16_t length )
441470{
442- volatile uint16_t tmp ;
471+ volatile uint16_t tmp_msw , tmp_lsw ;
443472 uint16_t * pdata = (uint16_t * )data ;
444473 uint16_t idx = 0 , len_align ;
445474 uint16_t last_word ;
475+ uint32_t blr_bitmap = 0 ;
446476 if (!(flashAddress >= FLASH_OTP_BASE && flashAddress <= FLASH_OTP_END )) {
447477 return -1 ;
448478 }
449479
480+ /* Reject misaligned destination address */
481+ if ((flashAddress & 0x01 ) != 0 ) {
482+ return -1 ;
483+ }
484+
450485 hal_flash_wait_complete (0 );
451486 hal_flash_wait_buffer_empty (0 );
452487 hal_flash_unlock ();
453488 hal_flash_clear_errors (0 );
454489
455-
456490 /* Truncate to 2B alignment */
457491 length = (length / 2 * 2 );
458492
459- while (idx < length && flashAddress <= FLASH_OTP_END - 1 ) {
493+ while (( idx < length ) && ( flashAddress <= FLASH_OTP_END - 1 ) ) {
460494 hal_flash_wait_complete (0 );
461495 /* Set PG bit */
462496 FLASH_CR |= FLASH_CR_PG ;
463- /* Program an OTP word (32 bits) */
464- * (volatile uint16_t * )flashAddress = * pdata ;
497+ /* Program an OTP word (16 bits) */
498+ * (volatile uint16_t * )flashAddress = pdata [0 ];
499+ /* Program a second OTP word (16 bits) */
500+ * (volatile uint16_t * )(flashAddress + sizeof (uint16_t )) = pdata [1 ];
465501 ISB ();
466502 DSB ();
503+
504+ /* Wait until not busy */
505+ while ((FLASH_SR & FLASH_SR_BSY ) != 0 )
506+ ;
507+
467508 /* Read it back */
468- tmp = * (volatile uint16_t * )flashAddress ;
469- if (tmp != * pdata ) {
509+ tmp_msw = * (volatile uint16_t * )flashAddress ;
510+ tmp_lsw = * (volatile uint16_t * )(flashAddress + sizeof (uint16_t ));
511+ if ((tmp_msw != pdata [0 ]) || (tmp_lsw != pdata [1 ])) {
470512 /* Provisioning failed. OTP already programmed? */
471513 while (1 )
472514 ;
473515 }
474516
475517 /* Clear PG bit */
476518 FLASH_CR &= ~FLASH_CR_PG ;
477- flashAddress += sizeof (uint16_t );
478- pdata ++ ;
479- idx += sizeof (uint16_t );
480- }
481519
520+ /* Advance to next two words */
521+ flashAddress += (2 * sizeof (uint16_t ));
522+ pdata += 2 ;
523+ idx += (2 * sizeof (uint16_t ));
524+ }
482525 hal_flash_lock ();
483526 return 0 ;
484527}
0 commit comments