
bootloader.elf:     file format elf32-littlearm

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00007588  08000000  08000000  00010000  2**8
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .relocate     0000024c  10006000  08007588  00026000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .bss          00000104  1000624c  080077d4  0002624c  2**2
                  ALLOC
  3 .stack        00000400  10006350  080078d8  0002624c  2**0
                  ALLOC
  4 .debug_info   00013365  00000000  00000000  0002624c  2**0
                  CONTENTS, READONLY, DEBUGGING
  5 .debug_abbrev 000030c1  00000000  00000000  000395b1  2**0
                  CONTENTS, READONLY, DEBUGGING
  6 .debug_loc    0000791f  00000000  00000000  0003c672  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_aranges 000008a0  00000000  00000000  00043f91  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_ranges 00000d08  00000000  00000000  00044831  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_macro  00029af3  00000000  00000000  00045539  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_line   0000a843  00000000  00000000  0006f02c  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_str    000edc1d  00000000  00000000  0007986f  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .comment      0000006e  00000000  00000000  0016748c  2**0
                  CONTENTS, READONLY
 13 .ARM.attributes 00000037  00000000  00000000  001674fa  2**0
                  CONTENTS, READONLY
 14 .debug_frame  000019a8  00000000  00000000  00167534  2**2
                  CONTENTS, READONLY, DEBUGGING

Disassembly of section .text:

08000000 <_sfixed>:
 8000000:	10007c00 	.word	0x10007c00
 8000004:	080000b1 	.word	0x080000b1
 8000008:	0800001d 	.word	0x0800001d
 800000c:	0800001f 	.word	0x0800001f
 8000010:	08000021 	.word	0x08000021
 8000014:	08000023 	.word	0x08000023
 8000018:	08000025 	.word	0x08000025

0800001c <NMI_Handler>:
 800001c:	be01      	bkpt	0x0001

0800001e <HardFault_Handler>:
 800001e:	be02      	bkpt	0x0002

08000020 <MemManage_Handler>:
 8000020:	be03      	bkpt	0x0003

08000022 <BusFault_Handler>:
 8000022:	be04      	bkpt	0x0004

08000024 <UsageFault_Handler>:
 8000024:	be05      	bkpt	0x0005
 8000026:	e7fe      	b.n	8000026 <UsageFault_Handler+0x2>

08000028 <bootloader_info>:
	...
 8000040:	08000305 	.word	0x08000305

08000044 <my_version_code>:
 8000044:	00000100 	.word	0x00000100
	...
 8000060:	20296328 	.word	0x20296328
 8000064:	79706f43 	.word	0x79706f43
 8000068:	68676972 	.word	0x68676972
 800006c:	30322074 	.word	0x30322074
 8000070:	62203831 	.word	0x62203831
 8000074:	6f432079 	.word	0x6f432079
 8000078:	696b6e69 	.word	0x696b6e69
 800007c:	49206574 	.word	0x49206574
 8000080:	202e636e 	.word	0x202e636e
 8000084:	540a200a 	.word	0x540a200a
 8000088:	20736968 	.word	0x20736968
 800008c:	63617073 	.word	0x63617073
 8000090:	6f662065 	.word	0x6f662065
 8000094:	65722072 	.word	0x65722072
 8000098:	202e746e 	.word	0x202e746e
 800009c:	7473754a 	.word	0x7473754a
 80000a0:	54423120 	.word	0x54423120
 80000a4:	65792f43 	.word	0x65792f43
 80000a8:	202e7261 	.word	0x202e7261
 80000ac:	000a200a 	.word	0x000a200a

080000b0 <reset_entry>:
 80000b0:	f000 f816 	bl	80000e0 <firewall_setup>
 80000b4:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff
 80000b8:	f04f 0100 	mov.w	r1, #0
 80000bc:	f04f 0200 	mov.w	r2, #0
 80000c0:	f04f 0300 	mov.w	r3, #0
 80000c4:	f000 f91e 	bl	8000304 <callgate_entry0>
 80000c8:	f248 0108 	movw	r1, #32776	; 0x8008
 80000cc:	ea4f 3101 	mov.w	r1, r1, lsl #12
 80000d0:	6808      	ldr	r0, [r1, #0]
 80000d2:	4685      	mov	sp, r0
 80000d4:	f04f 0001 	mov.w	r0, #1
 80000d8:	f8d1 e004 	ldr.w	lr, [r1, #4]
 80000dc:	4770      	bx	lr
	...

080000e0 <firewall_setup>:
    void
firewall_setup(void)
{
    // This is critical: without the clock enabled to "SYSCFG" we
    // can't tell the FW is enabled or not! Enabling it would also not work
    __HAL_RCC_SYSCFG_CLK_ENABLE();
 80000e0:	4b1c      	ldr	r3, [pc, #112]	; (8000154 <firewall_setup+0x74>)
// It's best if this is outside the firewall. After we return, we'll
// jump into setup code contained inside the firewall.
//
    void
firewall_setup(void)
{
 80000e2:	b500      	push	{lr}
    // This is critical: without the clock enabled to "SYSCFG" we
    // can't tell the FW is enabled or not! Enabling it would also not work
    __HAL_RCC_SYSCFG_CLK_ENABLE();
 80000e4:	6e1a      	ldr	r2, [r3, #96]	; 0x60
 80000e6:	f042 0201 	orr.w	r2, r2, #1
 80000ea:	661a      	str	r2, [r3, #96]	; 0x60
 80000ec:	6e1b      	ldr	r3, [r3, #96]	; 0x60
// It's best if this is outside the firewall. After we return, we'll
// jump into setup code contained inside the firewall.
//
    void
firewall_setup(void)
{
 80000ee:	b08b      	sub	sp, #44	; 0x2c
    // This is critical: without the clock enabled to "SYSCFG" we
    // can't tell the FW is enabled or not! Enabling it would also not work
    __HAL_RCC_SYSCFG_CLK_ENABLE();
 80000f0:	f003 0301 	and.w	r3, r3, #1
 80000f4:	9300      	str	r3, [sp, #0]
 80000f6:	9b00      	ldr	r3, [sp, #0]

    if(__HAL_FIREWALL_IS_ENABLED()) {
 80000f8:	4b17      	ldr	r3, [pc, #92]	; (8000158 <firewall_setup+0x78>)
 80000fa:	685b      	ldr	r3, [r3, #4]
 80000fc:	07db      	lsls	r3, r3, #31
 80000fe:	d525      	bpl.n	800014c <firewall_setup+0x6c>
    // REMINDERS: 
    // - cannot debug anything in boot loader w/ firewall enabled (no readback, no bkpt)
    // - with RDP=2, this protection still important or else python can read pairing secret
    // - in factory mode (RDP!=2), it's nice to have this disabled so we can debug still
    // - could look at RDP level here, but it would be harder to completely reset the bag number!
    if(check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))) {
 8000100:	2120      	movs	r1, #32
 8000102:	4816      	ldr	r0, [pc, #88]	; (800015c <firewall_setup+0x7c>)
 8000104:	f001 ff28 	bl	8001f58 <check_all_ones>
 8000108:	bb00      	cbnz	r0, 800014c <firewall_setup+0x6c>
        // ok. still virgin unit -- run w/o security
        return;
    }

    extern int firewall_starts;       // see startup.S ... aligned@256 (0x08000300)
    uint32_t    start = (uint32_t)&firewall_starts;
 800010a:	4b15      	ldr	r3, [pc, #84]	; (8000160 <firewall_setup+0x80>)
    //   but sensitive stuff is still there (which would allow bypass)
    // - so it's important to enable option bytes to set write-protect on entire bootloader
    // - to disable debug and complete protection, must enable write-protect "level 2"
    //

    FIREWALL_InitTypeDef init = {
 800010c:	9302      	str	r3, [sp, #8]
 800010e:	f1c3 6300 	rsb	r3, r3, #134217728	; 0x8000000
 8000112:	f503 43f0 	add.w	r3, r3, #30720	; 0x7800
 8000116:	9303      	str	r3, [sp, #12]
 8000118:	4b12      	ldr	r3, [pc, #72]	; (8000164 <firewall_setup+0x84>)
 800011a:	9304      	str	r3, [sp, #16]
 800011c:	9006      	str	r0, [sp, #24]
 800011e:	f44f 6300 	mov.w	r3, #2048	; 0x800
 8000122:	9007      	str	r0, [sp, #28]
 8000124:	9008      	str	r0, [sp, #32]
 8000126:	9009      	str	r0, [sp, #36]	; 0x24
        .VDataSegmentLength = 0,
        .VolatileDataExecution = 0,
        .VolatileDataShared = 0,
    };

    int rv = HAL_FIREWALL_Config((FIREWALL_InitTypeDef *)&init);
 8000128:	a802      	add	r0, sp, #8
    //   but sensitive stuff is still there (which would allow bypass)
    // - so it's important to enable option bytes to set write-protect on entire bootloader
    // - to disable debug and complete protection, must enable write-protect "level 2"
    //

    FIREWALL_InitTypeDef init = {
 800012a:	9305      	str	r3, [sp, #20]
        .VDataSegmentLength = 0,
        .VolatileDataExecution = 0,
        .VolatileDataShared = 0,
    };

    int rv = HAL_FIREWALL_Config((FIREWALL_InitTypeDef *)&init);
 800012c:	f000 f81e 	bl	800016c <HAL_FIREWALL_Config>
    if(rv) {
 8000130:	b100      	cbz	r0, 8000134 <firewall_setup+0x54>
        BREAKPOINT;
 8000132:	be00      	bkpt	0x0000
    }

    __HAL_FIREWALL_PREARM_DISABLE();
 8000134:	4b0c      	ldr	r3, [pc, #48]	; (8000168 <firewall_setup+0x88>)
 8000136:	6a1a      	ldr	r2, [r3, #32]
 8000138:	f022 0201 	bic.w	r2, r2, #1
 800013c:	621a      	str	r2, [r3, #32]
 800013e:	6a1b      	ldr	r3, [r3, #32]
 8000140:	f003 0301 	and.w	r3, r3, #1
 8000144:	9301      	str	r3, [sp, #4]
 8000146:	9b01      	ldr	r3, [sp, #4]
    HAL_FIREWALL_EnableFirewall();
 8000148:	f000 f88c 	bl	8000264 <HAL_FIREWALL_EnableFirewall>
}
 800014c:	b00b      	add	sp, #44	; 0x2c
 800014e:	f85d fb04 	ldr.w	pc, [sp], #4
 8000152:	bf00      	nop
 8000154:	40021000 	.word	0x40021000
 8000158:	40010000 	.word	0x40010000
 800015c:	08007850 	.word	0x08007850
 8000160:	08000300 	.word	0x08000300
 8000164:	08007800 	.word	0x08007800
 8000168:	40011c00 	.word	0x40011c00

0800016c <HAL_FIREWALL_Config>:
  * @param fw_init: Firewall initialization structure
  * @note  The API returns HAL_ERROR if the Firewall is already enabled.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_FIREWALL_Config(FIREWALL_InitTypeDef * fw_init)
{
 800016c:	b513      	push	{r0, r1, r4, lr}
  /* Check the Firewall initialization structure allocation */
  if(fw_init == NULL)
 800016e:	b908      	cbnz	r0, 8000174 <HAL_FIREWALL_Config+0x8>
  {
    return HAL_ERROR;
 8000170:	2001      	movs	r0, #1
 8000172:	e033      	b.n	80001dc <HAL_FIREWALL_Config+0x70>
  }

  /* Enable Firewall clock */
  __HAL_RCC_FIREWALL_CLK_ENABLE();
 8000174:	4b1a      	ldr	r3, [pc, #104]	; (80001e0 <HAL_FIREWALL_Config+0x74>)
 8000176:	6e1a      	ldr	r2, [r3, #96]	; 0x60
 8000178:	f042 0280 	orr.w	r2, r2, #128	; 0x80
 800017c:	661a      	str	r2, [r3, #96]	; 0x60
 800017e:	6e1b      	ldr	r3, [r3, #96]	; 0x60
 8000180:	f003 0380 	and.w	r3, r3, #128	; 0x80
 8000184:	9301      	str	r3, [sp, #4]
 8000186:	9b01      	ldr	r3, [sp, #4]

  /* Make sure that Firewall is not enabled already */
  if (__HAL_FIREWALL_IS_ENABLED() != RESET)
 8000188:	4b16      	ldr	r3, [pc, #88]	; (80001e4 <HAL_FIREWALL_Config+0x78>)
 800018a:	685b      	ldr	r3, [r3, #4]
 800018c:	07db      	lsls	r3, r3, #31
 800018e:	d5ef      	bpl.n	8000170 <HAL_FIREWALL_Config+0x4>
  assert_param(IS_FIREWALL_VOLATILEDATA_SHARE(fw_init->VolatileDataShared));

   /* Configuration */

  /* Protected code segment start address configuration */
  WRITE_REG(FIREWALL->CSSA, (FW_CSSA_ADD & fw_init->CodeSegmentStartAddress));
 8000190:	6802      	ldr	r2, [r0, #0]
 8000192:	4b15      	ldr	r3, [pc, #84]	; (80001e8 <HAL_FIREWALL_Config+0x7c>)
 8000194:	f022 427f 	bic.w	r2, r2, #4278190080	; 0xff000000
 8000198:	f022 02ff 	bic.w	r2, r2, #255	; 0xff
 800019c:	601a      	str	r2, [r3, #0]
    /* Protected code segment length configuration */
  WRITE_REG(FIREWALL->CSL, (FW_CSL_LENG & fw_init->CodeSegmentLength));
 800019e:	6841      	ldr	r1, [r0, #4]
 80001a0:	4a12      	ldr	r2, [pc, #72]	; (80001ec <HAL_FIREWALL_Config+0x80>)
 80001a2:	400a      	ands	r2, r1
 80001a4:	605a      	str	r2, [r3, #4]

  /* Protected non volatile data segment start address configuration */
  WRITE_REG(FIREWALL->NVDSSA, (FW_NVDSSA_ADD & fw_init->NonVDataSegmentStartAddress));
 80001a6:	6882      	ldr	r2, [r0, #8]
 80001a8:	f022 427f 	bic.w	r2, r2, #4278190080	; 0xff000000
 80001ac:	f022 02ff 	bic.w	r2, r2, #255	; 0xff
 80001b0:	609a      	str	r2, [r3, #8]
    /* Protected non volatile data segment length configuration */
  WRITE_REG(FIREWALL->NVDSL, (FW_NVDSL_LENG & fw_init->NonVDataSegmentLength));
 80001b2:	68c1      	ldr	r1, [r0, #12]
 80001b4:	4a0d      	ldr	r2, [pc, #52]	; (80001ec <HAL_FIREWALL_Config+0x80>)
 80001b6:	400a      	ands	r2, r1
 80001b8:	60da      	str	r2, [r3, #12]

  /* Protected volatile data segment start address configuration */
  WRITE_REG(FIREWALL->VDSSA, (FW_VDSSA_ADD & fw_init->VDataSegmentStartAddress));
 80001ba:	6901      	ldr	r1, [r0, #16]
 80001bc:	4a0c      	ldr	r2, [pc, #48]	; (80001f0 <HAL_FIREWALL_Config+0x84>)
 80001be:	400a      	ands	r2, r1
 80001c0:	611a      	str	r2, [r3, #16]
    /* Protected volatile data segment length configuration */
  WRITE_REG(FIREWALL->VDSL, (FW_VDSL_LENG & fw_init->VDataSegmentLength));
 80001c2:	6941      	ldr	r1, [r0, #20]
 80001c4:	4a0a      	ldr	r2, [pc, #40]	; (80001f0 <HAL_FIREWALL_Config+0x84>)
 80001c6:	400a      	ands	r2, r1
 80001c8:	615a      	str	r2, [r3, #20]

  /* Set Firewall Configuration Register VDE and VDS bits
     (volatile data execution and shared configuration) */
  MODIFY_REG(FIREWALL->CR, FW_CR_VDS|FW_CR_VDE, fw_init->VolatileDataExecution|fw_init->VolatileDataShared);
 80001ca:	6984      	ldr	r4, [r0, #24]
 80001cc:	69c1      	ldr	r1, [r0, #28]
 80001ce:	6a1a      	ldr	r2, [r3, #32]
 80001d0:	4321      	orrs	r1, r4
 80001d2:	f022 0206 	bic.w	r2, r2, #6
 80001d6:	430a      	orrs	r2, r1
 80001d8:	621a      	str	r2, [r3, #32]

  return HAL_OK;
 80001da:	2000      	movs	r0, #0
}
 80001dc:	b002      	add	sp, #8
 80001de:	bd10      	pop	{r4, pc}
 80001e0:	40021000 	.word	0x40021000
 80001e4:	40010000 	.word	0x40010000
 80001e8:	40011c00 	.word	0x40011c00
 80001ec:	003fff00 	.word	0x003fff00
 80001f0:	0001ffc0 	.word	0x0001ffc0

080001f4 <HAL_FIREWALL_GetConfig>:
void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)
{

  /* Enable Firewall clock, in case no Firewall configuration has been carried
     out up to this point */
  __HAL_RCC_FIREWALL_CLK_ENABLE();
 80001f4:	4b17      	ldr	r3, [pc, #92]	; (8000254 <HAL_FIREWALL_GetConfig+0x60>)

  /* Retrieve code segment protection setting */
  fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD);
  fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG);
 80001f6:	4918      	ldr	r1, [pc, #96]	; (8000258 <HAL_FIREWALL_GetConfig+0x64>)
void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)
{

  /* Enable Firewall clock, in case no Firewall configuration has been carried
     out up to this point */
  __HAL_RCC_FIREWALL_CLK_ENABLE();
 80001f8:	6e1a      	ldr	r2, [r3, #96]	; 0x60
 80001fa:	f042 0280 	orr.w	r2, r2, #128	; 0x80
 80001fe:	661a      	str	r2, [r3, #96]	; 0x60
 8000200:	6e1b      	ldr	r3, [r3, #96]	; 0x60
  *       is defined, this API can't be executed when the Firewall is enabled.
  * @note User should resort to __HAL_FIREWALL_GET_PREARM() macro to retrieve FPA bit status
  * @retval None
  */
void HAL_FIREWALL_GetConfig(FIREWALL_InitTypeDef * fw_config)
{
 8000202:	b082      	sub	sp, #8

  /* Enable Firewall clock, in case no Firewall configuration has been carried
     out up to this point */
  __HAL_RCC_FIREWALL_CLK_ENABLE();
 8000204:	f003 0380 	and.w	r3, r3, #128	; 0x80
 8000208:	9301      	str	r3, [sp, #4]
 800020a:	9b01      	ldr	r3, [sp, #4]

  /* Retrieve code segment protection setting */
  fw_config->CodeSegmentStartAddress = (READ_REG(FIREWALL->CSSA) & FW_CSSA_ADD);
 800020c:	4b13      	ldr	r3, [pc, #76]	; (800025c <HAL_FIREWALL_GetConfig+0x68>)
 800020e:	681a      	ldr	r2, [r3, #0]
 8000210:	f022 427f 	bic.w	r2, r2, #4278190080	; 0xff000000
 8000214:	f022 02ff 	bic.w	r2, r2, #255	; 0xff
 8000218:	6002      	str	r2, [r0, #0]
  fw_config->CodeSegmentLength = (READ_REG(FIREWALL->CSL) & FW_CSL_LENG);
 800021a:	685a      	ldr	r2, [r3, #4]
 800021c:	400a      	ands	r2, r1
 800021e:	6042      	str	r2, [r0, #4]

  /* Retrieve non volatile data segment protection setting */
  fw_config->NonVDataSegmentStartAddress = (READ_REG(FIREWALL->NVDSSA) & FW_NVDSSA_ADD);
 8000220:	689a      	ldr	r2, [r3, #8]
 8000222:	f022 427f 	bic.w	r2, r2, #4278190080	; 0xff000000
 8000226:	f022 02ff 	bic.w	r2, r2, #255	; 0xff
 800022a:	6082      	str	r2, [r0, #8]
  fw_config->NonVDataSegmentLength = (READ_REG(FIREWALL->NVDSL) & FW_NVDSL_LENG);
 800022c:	68da      	ldr	r2, [r3, #12]
 800022e:	4011      	ands	r1, r2
 8000230:	60c1      	str	r1, [r0, #12]

  /* Retrieve volatile data segment protection setting */
  fw_config->VDataSegmentStartAddress = (READ_REG(FIREWALL->VDSSA) & FW_VDSSA_ADD);
 8000232:	6919      	ldr	r1, [r3, #16]
 8000234:	4a0a      	ldr	r2, [pc, #40]	; (8000260 <HAL_FIREWALL_GetConfig+0x6c>)
 8000236:	4011      	ands	r1, r2
 8000238:	6101      	str	r1, [r0, #16]
  fw_config->VDataSegmentLength = (READ_REG(FIREWALL->VDSL) & FW_VDSL_LENG);
 800023a:	6959      	ldr	r1, [r3, #20]
 800023c:	400a      	ands	r2, r1
 800023e:	6142      	str	r2, [r0, #20]

  /* Retrieve volatile data execution setting */
  fw_config->VolatileDataExecution = (READ_REG(FIREWALL->CR) & FW_CR_VDE);
 8000240:	6a1a      	ldr	r2, [r3, #32]
 8000242:	f002 0204 	and.w	r2, r2, #4
 8000246:	6182      	str	r2, [r0, #24]

  /* Retrieve volatile data shared setting */
  fw_config->VolatileDataShared = (READ_REG(FIREWALL->CR) & FW_CR_VDS);
 8000248:	6a1b      	ldr	r3, [r3, #32]
 800024a:	f003 0302 	and.w	r3, r3, #2
 800024e:	61c3      	str	r3, [r0, #28]

  return;
}
 8000250:	b002      	add	sp, #8
 8000252:	4770      	bx	lr
 8000254:	40021000 	.word	0x40021000
 8000258:	003fff00 	.word	0x003fff00
 800025c:	40011c00 	.word	0x40011c00
 8000260:	0001ffc0 	.word	0x0001ffc0

08000264 <HAL_FIREWALL_EnableFirewall>:
  * @retval None
  */
void HAL_FIREWALL_EnableFirewall(void)
{
  /* Clears FWDIS bit of SYSCFG CFGR1 register */
  CLEAR_BIT(SYSCFG->CFGR1, SYSCFG_CFGR1_FWDIS);
 8000264:	4a02      	ldr	r2, [pc, #8]	; (8000270 <HAL_FIREWALL_EnableFirewall+0xc>)
 8000266:	6853      	ldr	r3, [r2, #4]
 8000268:	f023 0301 	bic.w	r3, r3, #1
 800026c:	6053      	str	r3, [r2, #4]
 800026e:	4770      	bx	lr
 8000270:	40010000 	.word	0x40010000

08000274 <HAL_FIREWALL_EnablePreArmFlag>:
  * @retval None
  */
void HAL_FIREWALL_EnablePreArmFlag(void)
{
  /* Set FPA bit */
  SET_BIT(FIREWALL->CR, FW_CR_FPA);
 8000274:	4a02      	ldr	r2, [pc, #8]	; (8000280 <HAL_FIREWALL_EnablePreArmFlag+0xc>)
 8000276:	6a13      	ldr	r3, [r2, #32]
 8000278:	f043 0301 	orr.w	r3, r3, #1
 800027c:	6213      	str	r3, [r2, #32]
 800027e:	4770      	bx	lr
 8000280:	40011c00 	.word	0x40011c00

08000284 <HAL_FIREWALL_DisablePreArmFlag>:
  * @retval None
  */
void HAL_FIREWALL_DisablePreArmFlag(void)
{
  /* Clear FPA bit */
  CLEAR_BIT(FIREWALL->CR, FW_CR_FPA);
 8000284:	4a02      	ldr	r2, [pc, #8]	; (8000290 <HAL_FIREWALL_DisablePreArmFlag+0xc>)
 8000286:	6a13      	ldr	r3, [r2, #32]
 8000288:	f023 0301 	bic.w	r3, r3, #1
 800028c:	6213      	str	r3, [r2, #32]
 800028e:	4770      	bx	lr
 8000290:	40011c00 	.word	0x40011c00
	...

08000300 <_firewall_start>:
 8000300:	0f193a11 	.word	0x0f193a11

08000304 <callgate_entry0>:
 8000304:	f246 0900 	movw	r9, #24576	; 0x6000
 8000308:	f2c1 0900 	movt	r9, #4096	; 0x1000
 800030c:	f44f 5ae0 	mov.w	sl, #7168	; 0x1c00
 8000310:	44ca      	add	sl, r9

08000312 <wipe_loop1>:
 8000312:	f849 ab04 	str.w	sl, [r9], #4
 8000316:	45d1      	cmp	r9, sl
 8000318:	d1fb      	bne.n	8000312 <wipe_loop1>
 800031a:	46cd      	mov	sp, r9
 800031c:	b500      	push	{lr}

0800031e <dispatcher>:
 800031e:	f000 f957 	bl	80005d0 <firewall_dispatch>
 8000322:	f85d eb04 	ldr.w	lr, [sp], #4
 8000326:	f246 0900 	movw	r9, #24576	; 0x6000
 800032a:	f2c1 0900 	movt	r9, #4096	; 0x1000
 800032e:	f44f 5ae0 	mov.w	sl, #7168	; 0x1c00
 8000332:	44ca      	add	sl, r9

08000334 <wipe_loop2>:
 8000334:	f849 0b04 	str.w	r0, [r9], #4
 8000338:	45d1      	cmp	r9, sl
 800033a:	d1fb      	bne.n	8000334 <wipe_loop2>
 800033c:	4770      	bx	lr
	...

08000340 <NVIC_SystemReset>:
  \details Acts as a special kind of Data Memory Barrier.
           It completes when all explicit memory accesses before this instruction complete.
 */
__attribute__((always_inline)) __STATIC_INLINE void __DSB(void)
{
  __ASM volatile ("dsb 0xF":::"memory");
 8000340:	f3bf 8f4f 	dsb	sy
__STATIC_INLINE void NVIC_SystemReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
 8000344:	4905      	ldr	r1, [pc, #20]	; (800035c <NVIC_SystemReset+0x1c>)
 */
__STATIC_INLINE void NVIC_SystemReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
 8000346:	4b06      	ldr	r3, [pc, #24]	; (8000360 <NVIC_SystemReset+0x20>)
                           (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
 8000348:	68ca      	ldr	r2, [r1, #12]
 */
__STATIC_INLINE void NVIC_SystemReset(void)
{
  __DSB();                                                          /* Ensure all outstanding memory accesses included
                                                                       buffered write are completed before reset */
  SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
 800034a:	f402 62e0 	and.w	r2, r2, #1792	; 0x700
 800034e:	4313      	orrs	r3, r2
 8000350:	60cb      	str	r3, [r1, #12]
 8000352:	f3bf 8f4f 	dsb	sy
  \brief   No Operation
  \details No Operation does nothing. This instruction can be used for code alignment purposes.
 */
__attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
{
  __ASM volatile ("nop");
 8000356:	bf00      	nop
 8000358:	e7fd      	b.n	8000356 <NVIC_SystemReset+0x16>
 800035a:	bf00      	nop
 800035c:	e000ed00 	.word	0xe000ed00
 8000360:	05fa0004 	.word	0x05fa0004

08000364 <good_addr>:
    static int
good_addr(const uint8_t *b, int minlen, int len, bool readonly)
{
    uint32_t x = (uint32_t)b;

    if(minlen) {
 8000364:	b111      	cbz	r1, 800036c <good_addr+0x8>
        if(!b) return EFAULT;               // gave no buffer
 8000366:	b188      	cbz	r0, 800038c <good_addr+0x28>
        if(len < minlen) return ERANGE;     // too small
 8000368:	4291      	cmp	r1, r2
 800036a:	dc11      	bgt.n	8000390 <good_addr+0x2c>
    }
        

    if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) {
 800036c:	f100 4260 	add.w	r2, r0, #3758096384	; 0xe0000000
 8000370:	f5b2 3fc0 	cmp.w	r2, #98304	; 0x18000
 8000374:	d30e      	bcc.n	8000394 <good_addr+0x30>
        // inside SRAM1, okay
        return 0;
    }

    if(!readonly) {
 8000376:	b17b      	cbz	r3, 8000398 <good_addr+0x34>
        return EPERM;
    }

    if((x >= FIRMWARE_START) && (x - FIRMWARE_START) < FW_MAX_LENGTH) {
 8000378:	f100 4078 	add.w	r0, r0, #4160749568	; 0xf8000000
 800037c:	f5a0 4000 	sub.w	r0, r0, #32768	; 0x8000
        // inside flash of main firmware (happens for QSTR's)
        return 0;
    }

    return EACCES;
 8000380:	f5b0 2f78 	cmp.w	r0, #1015808	; 0xf8000
 8000384:	bf34      	ite	cc
 8000386:	2000      	movcc	r0, #0
 8000388:	200d      	movcs	r0, #13
 800038a:	4770      	bx	lr
good_addr(const uint8_t *b, int minlen, int len, bool readonly)
{
    uint32_t x = (uint32_t)b;

    if(minlen) {
        if(!b) return EFAULT;               // gave no buffer
 800038c:	200e      	movs	r0, #14
 800038e:	4770      	bx	lr
        if(len < minlen) return ERANGE;     // too small
 8000390:	2022      	movs	r0, #34	; 0x22
 8000392:	4770      	bx	lr
    }
        

    if((x >= SRAM1_BASE) && ((x-SRAM1_BASE) < SRAM1_SIZE_MAX)) {
        // inside SRAM1, okay
        return 0;
 8000394:	2000      	movs	r0, #0
 8000396:	4770      	bx	lr
    }

    if(!readonly) {
        return EPERM;
 8000398:	2001      	movs	r0, #1
        // inside flash of main firmware (happens for QSTR's)
        return 0;
    }

    return EACCES;
}
 800039a:	4770      	bx	lr

0800039c <wipe_all_sram>:
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
        *dest = value;
 800039c:	4808      	ldr	r0, [pc, #32]	; (80003c0 <wipe_all_sram+0x24>)
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 800039e:	4a09      	ldr	r2, [pc, #36]	; (80003c4 <wipe_all_sram+0x28>)

// wipe_all_sram()
//
    static void
wipe_all_sram(void)
{
 80003a0:	f04f 5300 	mov.w	r3, #536870912	; 0x20000000
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
        *dest = value;
 80003a4:	f843 0b04 	str.w	r0, [r3], #4
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 80003a8:	4293      	cmp	r3, r2
 80003aa:	4905      	ldr	r1, [pc, #20]	; (80003c0 <wipe_all_sram+0x24>)
 80003ac:	d1fa      	bne.n	80003a4 <wipe_all_sram+0x8>
 80003ae:	4a06      	ldr	r2, [pc, #24]	; (80003c8 <wipe_all_sram+0x2c>)
 80003b0:	f04f 5380 	mov.w	r3, #268435456	; 0x10000000
        *dest = value;
 80003b4:	f843 1b04 	str.w	r1, [r3], #4
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 80003b8:	4293      	cmp	r3, r2
 80003ba:	d1fb      	bne.n	80003b4 <wipe_all_sram+0x18>
    const uint32_t noise = 0xdeadbeef;

    // wipe all of SRAM (except our own memory, which was already wiped)
    memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX);
    memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - BL_SRAM_SIZE);
}
 80003bc:	4770      	bx	lr
 80003be:	bf00      	nop
 80003c0:	deadbeef 	.word	0xdeadbeef
 80003c4:	20018000 	.word	0x20018000
 80003c8:	10006400 	.word	0x10006400

080003cc <fatal_error>:

// fatal_error(const char *msg)
//
    void
fatal_error(const char *msgvoid)
{
 80003cc:	b508      	push	{r3, lr}
    oled_setup();
 80003ce:	f000 fb8f 	bl	8000af0 <oled_setup>
    oled_show(screen_fatal);
 80003d2:	4802      	ldr	r0, [pc, #8]	; (80003dc <fatal_error+0x10>)
 80003d4:	f000 fc30 	bl	8000c38 <oled_show>
  \brief   Wait For Interrupt
  \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
 */
__attribute__((always_inline)) __STATIC_INLINE void __WFI(void)
{
  __ASM volatile ("wfi");
 80003d8:	bf30      	wfi
 80003da:	e7fd      	b.n	80003d8 <fatal_error+0xc>
 80003dc:	08006c59 	.word	0x08006c59

080003e0 <reboot_seed_setup>:
    uint8_t                     *reboot_seed = &reboot_seed_base[0];  // 32 bytes
    coldcardFirmwareHeader_t    *hdr_copy = (void *)&reboot_seed_base[32];
    uint32_t                    *boot_flags = (uint32_t *)RAM_BOOT_FLAGS;

    // can only do this once, and might be done already
    if(SYSCFG->SWPR != (1<<31)) {
 80003e0:	4b18      	ldr	r3, [pc, #96]	; (8000444 <reboot_seed_setup+0x64>)
 80003e2:	6a1b      	ldr	r3, [r3, #32]
 80003e4:	f1b3 4f00 	cmp.w	r3, #2147483648	; 0x80000000
// We need to know when we are rebooted, so write some noise
// into SRAM and lock it's value. Not secrets. One page = 1k bytes here.
//
    void
reboot_seed_setup(void)
{
 80003e8:	b510      	push	{r4, lr}
    uint8_t                     *reboot_seed = &reboot_seed_base[0];  // 32 bytes
    coldcardFirmwareHeader_t    *hdr_copy = (void *)&reboot_seed_base[32];
    uint32_t                    *boot_flags = (uint32_t *)RAM_BOOT_FLAGS;

    // can only do this once, and might be done already
    if(SYSCFG->SWPR != (1<<31)) {
 80003ea:	d02a      	beq.n	8000442 <reboot_seed_setup+0x62>
        ASSERT(((uint32_t)reboot_seed) == 0x10007c00);
 80003ec:	4c16      	ldr	r4, [pc, #88]	; (8000448 <reboot_seed_setup+0x68>)
 80003ee:	4b17      	ldr	r3, [pc, #92]	; (800044c <reboot_seed_setup+0x6c>)
 80003f0:	429c      	cmp	r4, r3
 80003f2:	d002      	beq.n	80003fa <reboot_seed_setup+0x1a>
 80003f4:	4816      	ldr	r0, [pc, #88]	; (8000450 <reboot_seed_setup+0x70>)
 80003f6:	f7ff ffe9 	bl	80003cc <fatal_error>
        ASSERT(((uint32_t)hdr_copy) == RAM_HEADER_BASE);

        // populate seed w/ noise
        memset(reboot_seed, 0x55, 1024);
 80003fa:	f44f 6280 	mov.w	r2, #1024	; 0x400
 80003fe:	2155      	movs	r1, #85	; 0x55
 8000400:	4620      	mov	r0, r4
 8000402:	f006 fa77 	bl	80068f4 <memset>
        rng_buffer(reboot_seed, 32);
 8000406:	2120      	movs	r1, #32
 8000408:	4620      	mov	r0, r4
 800040a:	f001 fe0d 	bl	8002028 <rng_buffer>

        // preserve a copy of the verified FW header
        memcpy(hdr_copy, FW_HDR, sizeof(coldcardFirmwareHeader_t));
 800040e:	2280      	movs	r2, #128	; 0x80
 8000410:	4910      	ldr	r1, [pc, #64]	; (8000454 <reboot_seed_setup+0x74>)
 8000412:	f104 0020 	add.w	r0, r4, #32
 8000416:	f006 fa47 	bl	80068a8 <memcpy>
// Write bag number (probably a string)
void flash_save_bag_number(const uint8_t new_number[32]);

// Are we operating in level2?
static inline bool flash_is_security_level2(void) {
    return ((FLASH->OPTR & FLASH_OPTR_RDP_Msk) == 0xCC);
 800041a:	4b0f      	ldr	r3, [pc, #60]	; (8000458 <reboot_seed_setup+0x78>)
        // document how we booted.
        uint32_t fl = 0;
        if(!flash_is_security_level2()) {
            fl |= RBF_FACTORY_MODE;
        }
        if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) {
 800041c:	4a0f      	ldr	r2, [pc, #60]	; (800045c <reboot_seed_setup+0x7c>)
 800041e:	6a1b      	ldr	r3, [r3, #32]
 8000420:	6811      	ldr	r1, [r2, #0]
 8000422:	4a0f      	ldr	r2, [pc, #60]	; (8000460 <reboot_seed_setup+0x80>)
        // preserve a copy of the verified FW header
        memcpy(hdr_copy, FW_HDR, sizeof(coldcardFirmwareHeader_t));

        // document how we booted.
        uint32_t fl = 0;
        if(!flash_is_security_level2()) {
 8000424:	b2db      	uxtb	r3, r3
            fl |= RBF_FACTORY_MODE;
 8000426:	2bcc      	cmp	r3, #204	; 0xcc
 8000428:	bf0c      	ite	eq
 800042a:	2300      	moveq	r3, #0
 800042c:	2302      	movne	r3, #2
        }
        if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) {
 800042e:	4291      	cmp	r1, r2
            fl |= RBF_FRESH_VERSION;
        }
        *boot_flags = fl;
 8000430:	4a0c      	ldr	r2, [pc, #48]	; (8000464 <reboot_seed_setup+0x84>)
        uint32_t fl = 0;
        if(!flash_is_security_level2()) {
            fl |= RBF_FACTORY_MODE;
        }
        if(sf_completed_upgrade == SF_COMPLETED_UPGRADE) {
            fl |= RBF_FRESH_VERSION;
 8000432:	bf08      	it	eq
 8000434:	f043 0301 	orreq.w	r3, r3, #1
        }
        *boot_flags = fl;
 8000438:	6013      	str	r3, [r2, #0]

        // lock it (top most page = 1k bytes)
        SYSCFG->SWPR = (1<<31);
 800043a:	4b02      	ldr	r3, [pc, #8]	; (8000444 <reboot_seed_setup+0x64>)
 800043c:	f04f 4200 	mov.w	r2, #2147483648	; 0x80000000
 8000440:	621a      	str	r2, [r3, #32]
 8000442:	bd10      	pop	{r4, pc}
 8000444:	40010000 	.word	0x40010000
 8000448:	10007c00 	.word	0x10007c00
 800044c:	10007c00 	.word	0x10007c00
 8000450:	08006960 	.word	0x08006960
 8000454:	0800bf80 	.word	0x0800bf80
 8000458:	40022000 	.word	0x40022000
 800045c:	1000634c 	.word	0x1000634c
 8000460:	b50d5c24 	.word	0xb50d5c24
 8000464:	10007ca0 	.word	0x10007ca0

08000468 <enter_dfu>:

// enter_dfu()
//
    void __attribute__((noreturn))
enter_dfu(void)
{
 8000468:	b507      	push	{r0, r1, r2, lr}
    const uint32_t noise = 0xDeadBeef;

    // clear the green light, if set
    ae_setup();
 800046a:	f001 ff21 	bl	80022b0 <ae_setup>
    ae_set_gpio(0);
 800046e:	2000      	movs	r0, #0
 8000470:	f002 fc43 	bl	8002cfa <ae_set_gpio>

    // Reset huge parts of the chip
    __HAL_RCC_APB1_FORCE_RESET();
 8000474:	4b1e      	ldr	r3, [pc, #120]	; (80004f0 <enter_dfu+0x88>)
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
        *dest = value;
 8000476:	481f      	ldr	r0, [pc, #124]	; (80004f4 <enter_dfu+0x8c>)
    ae_setup();
    ae_set_gpio(0);

    // Reset huge parts of the chip
    __HAL_RCC_APB1_FORCE_RESET();
    __HAL_RCC_APB1_RELEASE_RESET();
 8000478:	2200      	movs	r2, #0
    // clear the green light, if set
    ae_setup();
    ae_set_gpio(0);

    // Reset huge parts of the chip
    __HAL_RCC_APB1_FORCE_RESET();
 800047a:	f04f 31ff 	mov.w	r1, #4294967295	; 0xffffffff
 800047e:	6399      	str	r1, [r3, #56]	; 0x38
    __HAL_RCC_APB1_RELEASE_RESET();
 8000480:	639a      	str	r2, [r3, #56]	; 0x38

    __HAL_RCC_APB2_FORCE_RESET();
 8000482:	6419      	str	r1, [r3, #64]	; 0x40
    __HAL_RCC_APB2_RELEASE_RESET();
 8000484:	641a      	str	r2, [r3, #64]	; 0x40

    __HAL_RCC_AHB1_FORCE_RESET();
 8000486:	6299      	str	r1, [r3, #40]	; 0x28
    __HAL_RCC_AHB1_RELEASE_RESET();
 8000488:	629a      	str	r2, [r3, #40]	; 0x28
    // But not this; it borks things.
    __HAL_RCC_AHB2_FORCE_RESET();
    __HAL_RCC_AHB2_RELEASE_RESET();
#endif

    __HAL_RCC_AHB3_FORCE_RESET();
 800048a:	6319      	str	r1, [r3, #48]	; 0x30
    __HAL_RCC_AHB3_RELEASE_RESET();
 800048c:	631a      	str	r2, [r3, #48]	; 0x30

    __HAL_FIREWALL_PREARM_ENABLE();
 800048e:	f5a3 4374 	sub.w	r3, r3, #62464	; 0xf400
 8000492:	6a1a      	ldr	r2, [r3, #32]
 8000494:	f042 0201 	orr.w	r2, r2, #1
 8000498:	621a      	str	r2, [r3, #32]
 800049a:	6a1b      	ldr	r3, [r3, #32]
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 800049c:	4a16      	ldr	r2, [pc, #88]	; (80004f8 <enter_dfu+0x90>)
#endif

    __HAL_RCC_AHB3_FORCE_RESET();
    __HAL_RCC_AHB3_RELEASE_RESET();

    __HAL_FIREWALL_PREARM_ENABLE();
 800049e:	f003 0301 	and.w	r3, r3, #1
 80004a2:	9301      	str	r3, [sp, #4]
 80004a4:	9b01      	ldr	r3, [sp, #4]
 80004a6:	f04f 5300 	mov.w	r3, #536870912	; 0x20000000
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
        *dest = value;
 80004aa:	f843 0b04 	str.w	r0, [r3], #4
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 80004ae:	4293      	cmp	r3, r2
 80004b0:	4910      	ldr	r1, [pc, #64]	; (80004f4 <enter_dfu+0x8c>)
 80004b2:	d1fa      	bne.n	80004aa <enter_dfu+0x42>
 80004b4:	4a11      	ldr	r2, [pc, #68]	; (80004fc <enter_dfu+0x94>)
 80004b6:	f04f 5380 	mov.w	r3, #268435456	; 0x10000000
        *dest = value;
 80004ba:	f843 1b04 	str.w	r1, [r3], #4
// memset4()
//
    static inline void
memset4(uint32_t *dest, uint32_t value, uint32_t byte_len)
{
    for(; byte_len; byte_len-=4, dest++) {
 80004be:	4293      	cmp	r3, r2
 80004c0:	d1fb      	bne.n	80004ba <enter_dfu+0x52>
 80004c2:	4b0f      	ldr	r3, [pc, #60]	; (8000500 <enter_dfu+0x98>)
 80004c4:	6a1b      	ldr	r3, [r3, #32]
    // there is some way to trick us into DFU
    // after sensitive content in place.
    memset4((void *)SRAM1_BASE, noise, SRAM1_SIZE_MAX);
    memset4((void *)SRAM2_BASE, noise, SRAM2_SIZE - 1024);      // avoid seed area

    if(flash_is_security_level2()) {
 80004c6:	b2db      	uxtb	r3, r3
 80004c8:	2bcc      	cmp	r3, #204	; 0xcc
 80004ca:	d101      	bne.n	80004d0 <enter_dfu+0x68>
 80004cc:	bf30      	wfi
 80004ce:	e7fd      	b.n	80004cc <enter_dfu+0x64>
        // cannot do DFU in RDP=2, so just die. Helps to preserve screen
        LOCKUP_FOREVER();
    }

    // Reset clocks.
    HAL_RCC_DeInit();
 80004d0:	f003 fca8 	bl	8003e24 <HAL_RCC_DeInit>

    // move system ROM into 0x0
    __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
 80004d4:	4a0b      	ldr	r2, [pc, #44]	; (8000504 <enter_dfu+0x9c>)
 80004d6:	6813      	ldr	r3, [r2, #0]
 80004d8:	f023 0307 	bic.w	r3, r3, #7
 80004dc:	f043 0301 	orr.w	r3, r3, #1
 80004e0:	6013      	str	r3, [r2, #0]

    // simulate a reset vector
    __ASM volatile ("movs r0, #0\n"
 80004e2:	2000      	movs	r0, #0
 80004e4:	6803      	ldr	r3, [r0, #0]
 80004e6:	f383 8808 	msr	MSP, r3
 80004ea:	6843      	ldr	r3, [r0, #4]
 80004ec:	4798      	blx	r3
 80004ee:	bf00      	nop
 80004f0:	40021000 	.word	0x40021000
 80004f4:	deadbeef 	.word	0xdeadbeef
 80004f8:	20018000 	.word	0x20018000
 80004fc:	10007c00 	.word	0x10007c00
 8000500:	40022000 	.word	0x40022000
 8000504:	40010000 	.word	0x40010000

08000508 <dfu_by_request>:

// dfu_by_request()
//
    void
dfu_by_request(void)
{
 8000508:	b508      	push	{r3, lr}
 800050a:	4b05      	ldr	r3, [pc, #20]	; (8000520 <dfu_by_request+0x18>)
 800050c:	6a1b      	ldr	r3, [r3, #32]
    if(flash_is_security_level2()) {
 800050e:	b2db      	uxtb	r3, r3
 8000510:	2bcc      	cmp	r3, #204	; 0xcc
 8000512:	d004      	beq.n	800051e <dfu_by_request+0x16>
        // cannot get into DFU when secure
        // so do nothing
        return;
    }

    oled_show(screen_dfu);
 8000514:	4803      	ldr	r0, [pc, #12]	; (8000524 <dfu_by_request+0x1c>)
 8000516:	f000 fb8f 	bl	8000c38 <oled_show>
    enter_dfu();
 800051a:	f7ff ffa5 	bl	8000468 <enter_dfu>
 800051e:	bd08      	pop	{r3, pc}
 8000520:	40022000 	.word	0x40022000
 8000524:	08006cc3 	.word	0x08006cc3

08000528 <system_startup>:
//
// Called only on system boot.
//
    void
system_startup(void)
{
 8000528:	b510      	push	{r4, lr}
    // configure clocks first
    clocks_setup();
 800052a:	f001 fa6f 	bl	8001a0c <clocks_setup>

#if RELEASE
    // security check: should we be in protected mode? Was there some UV-C bitrot perhaps?
    if(!check_all_ones(rom_secrets->bag_number, sizeof(rom_secrets->bag_number))
 800052e:	2120      	movs	r1, #32
 8000530:	4821      	ldr	r0, [pc, #132]	; (80005b8 <system_startup+0x90>)
 8000532:	f001 fd11 	bl	8001f58 <check_all_ones>
 8000536:	b938      	cbnz	r0, 8000548 <system_startup+0x20>
 8000538:	4b20      	ldr	r3, [pc, #128]	; (80005bc <system_startup+0x94>)
 800053a:	6a1b      	ldr	r3, [r3, #32]
            && !flash_is_security_level2()
 800053c:	b2db      	uxtb	r3, r3
 800053e:	2bcc      	cmp	r3, #204	; 0xcc
 8000540:	d002      	beq.n	8000548 <system_startup+0x20>
    ) {
        // yikes. recovery: do lockdown... we should be/(thought we were) locked already
        flash_lockdown_hard(OB_RDP_LEVEL_2);
 8000542:	20cc      	movs	r0, #204	; 0xcc
 8000544:	f001 fc92 	bl	8001e6c <flash_lockdown_hard>
    }
#endif

    // workaround to get into DFU from micropython
    // LATER: none of this is useful with RDP=2
    if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) {
 8000548:	4c1d      	ldr	r4, [pc, #116]	; (80005c0 <system_startup+0x98>)
 800054a:	491e      	ldr	r1, [pc, #120]	; (80005c4 <system_startup+0x9c>)
 800054c:	2208      	movs	r2, #8
 800054e:	4620      	mov	r0, r4
 8000550:	f006 f99b 	bl	800688a <memcmp>
 8000554:	b938      	cbnz	r0, 8000566 <system_startup+0x3e>
        dfu_flag->magic[0] = 0;
 8000556:	7020      	strb	r0, [r4, #0]

        // still see a flash here, but that's proof it works.
        oled_setup();
 8000558:	f000 faca 	bl	8000af0 <oled_setup>
        oled_show(dfu_flag->screen);
 800055c:	68a0      	ldr	r0, [r4, #8]
 800055e:	f000 fb6b 	bl	8000c38 <oled_show>

        enter_dfu();
 8000562:	f7ff ff81 	bl	8000468 <enter_dfu>
        // NOT-REACHED
    }

    // clear and setup OLED display
    oled_setup();
 8000566:	f000 fac3 	bl	8000af0 <oled_setup>
    oled_show_progress(screen_verify, 0);
 800056a:	2100      	movs	r1, #0
 800056c:	4816      	ldr	r0, [pc, #88]	; (80005c8 <system_startup+0xa0>)
 800056e:	f000 fba3 	bl	8000cb8 <oled_show_progress>

    // won't always need it, but enable RNG anyway
    rng_setup();
 8000572:	f001 fd2d 	bl	8001fd0 <rng_setup>

    // wipe all of SRAM (except our own memory, which was already wiped)
    wipe_all_sram();
 8000576:	f7ff ff11 	bl	800039c <wipe_all_sram>

    // config pins
    gpio_setup();
 800057a:	f002 fd83 	bl	8003084 <gpio_setup>
    ae_setup();
 800057e:	f001 fe97 	bl	80022b0 <ae_setup>
    ae_set_gpio(0);         // not checking return on purpose
 8000582:	2000      	movs	r0, #0
 8000584:	f002 fbb9 	bl	8002cfa <ae_set_gpio>

    // protect our flash, and/or check it's protected 
    // - and pick pairing secret if we don't already have one
    // - may also do one-time setup of 508a
    // - note: ae_setup must already be called, since it can talk to that
    flash_setup();
 8000588:	f001 fbfc 	bl	8001d84 <flash_setup>

    // escape into DFU
    if(dfu_button_pressed()) dfu_by_request();
 800058c:	f002 fdae 	bl	80030ec <dfu_button_pressed>
 8000590:	b108      	cbz	r0, 8000596 <system_startup+0x6e>
 8000592:	f7ff ffb9 	bl	8000508 <dfu_by_request>

    // maybe upgrade to a firmware image found in sflash
    sf_firmware_upgrade();
 8000596:	f003 fb87 	bl	8003ca8 <sf_firmware_upgrade>

    // SLOW part: check firmware is legit; else enter DFU
    // - may die due to downgrade attack or unsigned/badly signed image
    verify_firmware();
 800059a:	f001 f9ed 	bl	8001978 <verify_firmware>

    // .. for slow people, check again; last chance
    if(dfu_button_pressed()) dfu_by_request();
 800059e:	f002 fda5 	bl	80030ec <dfu_button_pressed>
 80005a2:	b108      	cbz	r0, 80005a8 <system_startup+0x80>
 80005a4:	f7ff ffb0 	bl	8000508 <dfu_by_request>

    // track reboots, capture firmware hdr used
    // - must be near end of boot process, ie: here.
    reboot_seed_setup();
 80005a8:	f7ff ff1a 	bl	80003e0 <reboot_seed_setup>

    // load a blank-ish screen, so that 
    // if the firmware crashes, we are showing
    // something reasonable
    oled_show(screen_blank);
 80005ac:	4807      	ldr	r0, [pc, #28]	; (80005cc <system_startup+0xa4>)
}
 80005ae:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
    reboot_seed_setup();

    // load a blank-ish screen, so that 
    // if the firmware crashes, we are showing
    // something reasonable
    oled_show(screen_blank);
 80005b2:	f000 bb41 	b.w	8000c38 <oled_show>
 80005b6:	bf00      	nop
 80005b8:	08007850 	.word	0x08007850
 80005bc:	40022000 	.word	0x40022000
 80005c0:	20008000 	.word	0x20008000
 80005c4:	08006967 	.word	0x08006967
 80005c8:	08006ad6 	.word	0x08006ad6
 80005cc:	08006aa9 	.word	0x08006aa9

080005d0 <firewall_dispatch>:
//
    __attribute__ ((used))
    int
firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
                        uint32_t arg2, uint32_t incoming_lr)
{
 80005d0:	b570      	push	{r4, r5, r6, lr}
 80005d2:	b0a8      	sub	sp, #160	; 0xa0
 80005d4:	4616      	mov	r6, r2
 80005d6:	9301      	str	r3, [sp, #4]
    __disable_irq();
#endif

    // "1=any code executed outside the protected segment will close the Firewall"
    // "0=.. will reset the processor"
    __HAL_FIREWALL_PREARM_DISABLE();
 80005d8:	4bb4      	ldr	r3, [pc, #720]	; (80008ac <firewall_dispatch+0x2dc>)
 80005da:	6a1a      	ldr	r2, [r3, #32]
 80005dc:	f022 0201 	bic.w	r2, r2, #1
//
    __attribute__ ((used))
    int
firewall_dispatch(int method_num, uint8_t *buf_io, int len_in,
                        uint32_t arg2, uint32_t incoming_lr)
{
 80005e0:	460d      	mov	r5, r1
 80005e2:	992c      	ldr	r1, [sp, #176]	; 0xb0
    __disable_irq();
#endif

    // "1=any code executed outside the protected segment will close the Firewall"
    // "0=.. will reset the processor"
    __HAL_FIREWALL_PREARM_DISABLE();
 80005e4:	621a      	str	r2, [r3, #32]
 80005e6:	6a1b      	ldr	r3, [r3, #32]
 80005e8:	f003 0301 	and.w	r3, r3, #1
 80005ec:	9303      	str	r3, [sp, #12]
    //   using read/write in place.
    // - use arg2 use when a simple number is needed; never a pointer!
    // - mpy may provide a pointer to flash if we give it a qstr or small value, and if
    //   we're reading only, that's fine.

    if(len_in > 255) {
 80005ee:	2eff      	cmp	r6, #255	; 0xff
    __disable_irq();
#endif

    // "1=any code executed outside the protected segment will close the Firewall"
    // "0=.. will reset the processor"
    __HAL_FIREWALL_PREARM_DISABLE();
 80005f0:	9b03      	ldr	r3, [sp, #12]
    //   using read/write in place.
    // - use arg2 use when a simple number is needed; never a pointer!
    // - mpy may provide a pointer to flash if we give it a qstr or small value, and if
    //   we're reading only, that's fine.

    if(len_in > 255) {
 80005f2:	f300 81e2 	bgt.w	80009ba <firewall_dispatch+0x3ea>

    // Use these macros
#define REQUIRE_IN_ONLY(x)   if((rv = good_addr(buf_io, (x), len_in, true))) { goto fail; }
#define REQUIRE_OUT(x)       if((rv = good_addr(buf_io, (x), len_in, false))) { goto fail; }

    switch(method_num) {
 80005f6:	3001      	adds	r0, #1
 80005f8:	2816      	cmp	r0, #22
 80005fa:	f200 81e2 	bhi.w	80009c2 <firewall_dispatch+0x3f2>
 80005fe:	e8df f010 	tbh	[pc, r0, lsl #1]
 8000602:	01d3      	.short	0x01d3
 8000604:	002f0017 	.word	0x002f0017
 8000608:	0076004e 	.word	0x0076004e
 800060c:	00a90089 	.word	0x00a90089
 8000610:	01e001e0 	.word	0x01e001e0
 8000614:	01e001e0 	.word	0x01e001e0
 8000618:	01e001e0 	.word	0x01e001e0
 800061c:	01e000b1 	.word	0x01e000b1
 8000620:	00c001e0 	.word	0x00c001e0
 8000624:	00f200de 	.word	0x00f200de
 8000628:	01310106 	.word	0x01310106
 800062c:	01920180 	.word	0x01920180
        case 0: {
            REQUIRE_OUT(64);
 8000630:	2300      	movs	r3, #0
 8000632:	4632      	mov	r2, r6
 8000634:	2140      	movs	r1, #64	; 0x40
 8000636:	4628      	mov	r0, r5
 8000638:	f7ff fe94 	bl	8000364 <good_addr>
 800063c:	4604      	mov	r4, r0
 800063e:	2800      	cmp	r0, #0
 8000640:	f040 81c4 	bne.w	80009cc <firewall_dispatch+0x3fc>

            // Return my version string
            memset(buf_io, 0, len_in);
 8000644:	4632      	mov	r2, r6
 8000646:	4601      	mov	r1, r0
 8000648:	4628      	mov	r0, r5
 800064a:	f006 f953 	bl	80068f4 <memset>
            strlcpy((char *)buf_io, version_string, len_in);
 800064e:	4632      	mov	r2, r6
 8000650:	4997      	ldr	r1, [pc, #604]	; (80008b0 <firewall_dispatch+0x2e0>)
 8000652:	4628      	mov	r0, r5
 8000654:	f006 f956 	bl	8006904 <strlcpy>

            rv = strlen(version_string);
 8000658:	4895      	ldr	r0, [pc, #596]	; (80008b0 <firewall_dispatch+0x2e0>)
 800065a:	f006 f968 	bl	800692e <strlen>
 800065e:	e180      	b.n	8000962 <firewall_dispatch+0x392>
        }

        case 1: {
            // Perform SHA256 over ourselves, with 32-bits of salt, to imply we 
            // haven't stored valid responses.
            REQUIRE_OUT(32);
 8000660:	2300      	movs	r3, #0
 8000662:	4632      	mov	r2, r6
 8000664:	2120      	movs	r1, #32
 8000666:	4628      	mov	r0, r5
 8000668:	f7ff fe7c 	bl	8000364 <good_addr>
 800066c:	4604      	mov	r4, r0
 800066e:	2800      	cmp	r0, #0
 8000670:	f040 81ac 	bne.w	80009cc <firewall_dispatch+0x3fc>

            SHA256_CTX  ctx;
            sha256_init(&ctx);
 8000674:	a80c      	add	r0, sp, #48	; 0x30
 8000676:	f004 fe9b 	bl	80053b0 <sha256_init>
            sha256_update(&ctx, (void *)&arg2, 4);
 800067a:	2204      	movs	r2, #4
 800067c:	eb0d 0102 	add.w	r1, sp, r2
 8000680:	a80c      	add	r0, sp, #48	; 0x30
 8000682:	f004 febf 	bl	8005404 <sha256_update>
            sha256_update(&ctx, (void *)BL_FLASH_BASE, BL_FLASH_SIZE);
 8000686:	a80c      	add	r0, sp, #48	; 0x30
 8000688:	f44f 42f0 	mov.w	r2, #30720	; 0x7800
 800068c:	f04f 6100 	mov.w	r1, #134217728	; 0x8000000
 8000690:	f004 feb8 	bl	8005404 <sha256_update>
            sha256_final(&ctx, buf_io);
 8000694:	4629      	mov	r1, r5
 8000696:	a80c      	add	r0, sp, #48	; 0x30
 8000698:	f004 fed2 	bl	8005440 <sha256_final>
 800069c:	e196      	b.n	80009cc <firewall_dispatch+0x3fc>
 800069e:	4b85      	ldr	r3, [pc, #532]	; (80008b4 <firewall_dispatch+0x2e4>)
 80006a0:	6a1d      	ldr	r5, [r3, #32]
            bool secure = flash_is_security_level2();

            // Go into DFU mode. It's a one-way trip.
            // Also used to show some "fatal" screens w/ memory wipe.

            switch(arg2) {
 80006a2:	9b01      	ldr	r3, [sp, #4]
 80006a4:	2b02      	cmp	r3, #2
 80006a6:	b2ed      	uxtb	r5, r5
 80006a8:	d004      	beq.n	80006b4 <firewall_dispatch+0xe4>
 80006aa:	2b03      	cmp	r3, #3
 80006ac:	d009      	beq.n	80006c2 <firewall_dispatch+0xf2>
 80006ae:	2b01      	cmp	r3, #1
 80006b0:	d102      	bne.n	80006b8 <firewall_dispatch+0xe8>
 80006b2:	e008      	b.n	80006c6 <firewall_dispatch+0xf6>
                case 1:
                    // in case some way for Micropython to detect it.
                    scr = screen_downgrade;
                    break;
                case 2:
                    scr = screen_blank;
 80006b4:	4c80      	ldr	r4, [pc, #512]	; (80008b8 <firewall_dispatch+0x2e8>)
 80006b6:	e007      	b.n	80006c8 <firewall_dispatch+0xf8>

            switch(arg2) {
                default:
                case 0:
                    // enter DFU for firmware upgrades
                    if(secure) {
 80006b8:	2dcc      	cmp	r5, #204	; 0xcc
 80006ba:	f000 8186 	beq.w	80009ca <firewall_dispatch+0x3fa>
                        // we cannot support DFU in secure mode anymore
                        rv = EPERM;
                        goto fail;
                    }
                    scr = screen_dfu;
 80006be:	4c7f      	ldr	r4, [pc, #508]	; (80008bc <firewall_dispatch+0x2ec>)
 80006c0:	e002      	b.n	80006c8 <firewall_dispatch+0xf8>
                    break;
                case 2:
                    scr = screen_blank;
                    break;
                case 3:
                    scr = screen_brick;
 80006c2:	4c7f      	ldr	r4, [pc, #508]	; (80008c0 <firewall_dispatch+0x2f0>)
                    break;
 80006c4:	e000      	b.n	80006c8 <firewall_dispatch+0xf8>
                    }
                    scr = screen_dfu;
                    break;
                case 1:
                    // in case some way for Micropython to detect it.
                    scr = screen_downgrade;
 80006c6:	4c7f      	ldr	r4, [pc, #508]	; (80008c4 <firewall_dispatch+0x2f4>)
                case 3:
                    scr = screen_brick;
                    break;
            }

            oled_setup();
 80006c8:	f000 fa12 	bl	8000af0 <oled_setup>
            oled_show(scr);
 80006cc:	4620      	mov	r0, r4
 80006ce:	f000 fab3 	bl	8000c38 <oled_show>

            wipe_all_sram();
 80006d2:	f7ff fe63 	bl	800039c <wipe_all_sram>

            if(secure) {
 80006d6:	2dcc      	cmp	r5, #204	; 0xcc
 80006d8:	d101      	bne.n	80006de <firewall_dispatch+0x10e>
 80006da:	bf30      	wfi
 80006dc:	e7fd      	b.n	80006da <firewall_dispatch+0x10a>
            } else {
                // Cannot just call enter_dfu() because it doesn't work well
                // once Micropython has configured so much stuff in the chip.

                // Leave a reminder to ourselves
                memcpy(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic));
 80006de:	497a      	ldr	r1, [pc, #488]	; (80008c8 <firewall_dispatch+0x2f8>)
 80006e0:	4a7a      	ldr	r2, [pc, #488]	; (80008cc <firewall_dispatch+0x2fc>)
 80006e2:	6808      	ldr	r0, [r1, #0]
 80006e4:	6849      	ldr	r1, [r1, #4]
 80006e6:	4613      	mov	r3, r2
 80006e8:	c303      	stmia	r3!, {r0, r1}
                dfu_flag->screen = scr;
 80006ea:	6094      	str	r4, [r2, #8]
 80006ec:	e00e      	b.n	800070c <firewall_dispatch+0x13c>
            break;
        }

        case 3:
            // logout: wipe all of memory and lock up. Must powercycle to recover.
            switch(arg2) { 
 80006ee:	9b01      	ldr	r3, [sp, #4]
 80006f0:	b10b      	cbz	r3, 80006f6 <firewall_dispatch+0x126>
 80006f2:	2b02      	cmp	r3, #2
 80006f4:	d102      	bne.n	80006fc <firewall_dispatch+0x12c>
                case 0:
                case 2:
                    oled_show(screen_logout);
 80006f6:	4876      	ldr	r0, [pc, #472]	; (80008d0 <firewall_dispatch+0x300>)
 80006f8:	f000 fa9e 	bl	8000c38 <oled_show>
                case 1:
                    // leave screen untouched
                    break;
            }

            wipe_all_sram();
 80006fc:	f7ff fe4e 	bl	800039c <wipe_all_sram>

            if(arg2 == 2) {
 8000700:	9b01      	ldr	r3, [sp, #4]
 8000702:	2b02      	cmp	r3, #2
 8000704:	d104      	bne.n	8000710 <firewall_dispatch+0x140>
                // need some time to show OLED contents
                delay_ms(100);
 8000706:	2064      	movs	r0, #100	; 0x64
 8000708:	f002 fc90 	bl	800302c <delay_ms>

                // reboot so we can "login" again
                NVIC_SystemReset();
 800070c:	f7ff fe18 	bl	8000340 <NVIC_SystemReset>
 8000710:	bf30      	wfi
 8000712:	e7fd      	b.n	8000710 <firewall_dispatch+0x140>
            LOCKUP_FOREVER()
            break;

        case 4:
            // attempt to control the GPIO (won't work for 1)
            ae_setup();
 8000714:	f001 fdcc 	bl	80022b0 <ae_setup>
            ae_keep_alive();
 8000718:	f001 fe06 	bl	8002328 <ae_keep_alive>
            switch(arg2) {
 800071c:	9b01      	ldr	r3, [sp, #4]
 800071e:	2b02      	cmp	r3, #2
 8000720:	d008      	beq.n	8000734 <firewall_dispatch+0x164>
 8000722:	2b03      	cmp	r3, #3
 8000724:	d00a      	beq.n	800073c <firewall_dispatch+0x16c>
 8000726:	2b01      	cmp	r3, #1
 8000728:	d002      	beq.n	8000730 <firewall_dispatch+0x160>
                default:
                case 0:     // read state
                    rv = ae_get_gpio();
 800072a:	f002 fb0e 	bl	8002d4a <ae_get_gpio>
 800072e:	e118      	b.n	8000962 <firewall_dispatch+0x392>
                    break;
                case 1:     // clear it (can work anytime)
                    rv = ae_set_gpio(0);
 8000730:	2000      	movs	r0, #0
 8000732:	e000      	b.n	8000736 <firewall_dispatch+0x166>
                    break;
                case 2:     // set it (will always fail)
                    rv = ae_set_gpio(1);
 8000734:	2001      	movs	r0, #1
 8000736:	f002 fae0 	bl	8002cfa <ae_set_gpio>
 800073a:	e112      	b.n	8000962 <firewall_dispatch+0x392>

                case 3: {     // do a verify and see if it maybe goes green
                    uint8_t fw_digest[32], world_digest[32];

                    // takes time, shows progress bar
                    checksum_flash(fw_digest, world_digest);
 800073c:	a90c      	add	r1, sp, #48	; 0x30
 800073e:	a804      	add	r0, sp, #16
 8000740:	f001 f82e 	bl	80017a0 <checksum_flash>

                    rv = ae_set_gpio_secure(world_digest);
 8000744:	a80c      	add	r0, sp, #48	; 0x30
 8000746:	f002 faf3 	bl	8002d30 <ae_set_gpio_secure>
 800074a:	4604      	mov	r4, r0

                    oled_show(screen_blank);
 800074c:	485a      	ldr	r0, [pc, #360]	; (80008b8 <firewall_dispatch+0x2e8>)
 800074e:	f000 fa73 	bl	8000c38 <oled_show>
 8000752:	e13b      	b.n	80009cc <firewall_dispatch+0x3fc>
        case 5:     
            // Are we a brick?
            // if the pairing secret doesn't work anymore, that
            // means we've been bricked.
            // TODO: also report hardware issue, and non-configured states
            ae_setup();
 8000754:	f001 fdac 	bl	80022b0 <ae_setup>
            rv = (ae_pair_unlock() != 0);
 8000758:	f002 f804 	bl	8002764 <ae_pair_unlock>
 800075c:	1c04      	adds	r4, r0, #0
 800075e:	bf18      	it	ne
 8000760:	2401      	movne	r4, #1
            break;
 8000762:	e133      	b.n	80009cc <firewall_dispatch+0x3fc>

        case 12:
            // read the DFU button (used for selftest at least)
            REQUIRE_OUT(1);
 8000764:	2300      	movs	r3, #0
 8000766:	4632      	mov	r2, r6
 8000768:	2101      	movs	r1, #1
 800076a:	4628      	mov	r0, r5
 800076c:	f7ff fdfa 	bl	8000364 <good_addr>
 8000770:	4604      	mov	r4, r0
 8000772:	2800      	cmp	r0, #0
 8000774:	f040 812a 	bne.w	80009cc <firewall_dispatch+0x3fc>
            gpio_setup();
 8000778:	f002 fc84 	bl	8003084 <gpio_setup>
            buf_io[0] = dfu_button_pressed();
 800077c:	f002 fcb6 	bl	80030ec <dfu_button_pressed>
 8000780:	e0cf      	b.n	8000922 <firewall_dispatch+0x352>
            break;

        case 15: {
            // Read a dataslot directly. Will fail on 
            // encrypted slots.
            if(len_in != 4 && len_in != 32 && len_in != 72) {
 8000782:	2e04      	cmp	r6, #4
 8000784:	d004      	beq.n	8000790 <firewall_dispatch+0x1c0>
 8000786:	2e20      	cmp	r6, #32
 8000788:	d002      	beq.n	8000790 <firewall_dispatch+0x1c0>
 800078a:	2e48      	cmp	r6, #72	; 0x48
 800078c:	f040 8115 	bne.w	80009ba <firewall_dispatch+0x3ea>
                rv = ERANGE;
            } else {
                REQUIRE_OUT(4);
 8000790:	2300      	movs	r3, #0
 8000792:	4632      	mov	r2, r6
 8000794:	2104      	movs	r1, #4
 8000796:	4628      	mov	r0, r5
 8000798:	f7ff fde4 	bl	8000364 <good_addr>
 800079c:	4604      	mov	r4, r0
 800079e:	2800      	cmp	r0, #0
 80007a0:	f040 8114 	bne.w	80009cc <firewall_dispatch+0x3fc>

                ae_setup();
 80007a4:	f001 fd84 	bl	80022b0 <ae_setup>
                if(ae_read_data_slot(arg2 & 0xf, buf_io, len_in)) {
 80007a8:	9801      	ldr	r0, [sp, #4]
 80007aa:	4632      	mov	r2, r6
 80007ac:	4629      	mov	r1, r5
 80007ae:	f000 000f 	and.w	r0, r0, #15
 80007b2:	f002 fa11 	bl	8002bd8 <ae_read_data_slot>
 80007b6:	2800      	cmp	r0, #0
 80007b8:	f040 8101 	bne.w	80009be <firewall_dispatch+0x3ee>
 80007bc:	e09f      	b.n	80008fe <firewall_dispatch+0x32e>
            break;
        }

        case 16: {
            // Provide the 2 words for anti-phishing.
            REQUIRE_OUT(MAX_PIN_LEN);
 80007be:	2300      	movs	r3, #0
 80007c0:	4632      	mov	r2, r6
 80007c2:	2120      	movs	r1, #32
 80007c4:	4628      	mov	r0, r5
 80007c6:	f7ff fdcd 	bl	8000364 <good_addr>
 80007ca:	4604      	mov	r4, r0
 80007cc:	2800      	cmp	r0, #0
 80007ce:	f040 80fd 	bne.w	80009cc <firewall_dispatch+0x3fc>

            // arg2: length of pin.
            if((arg2 < 1) || (arg2 > MAX_PIN_LEN)) {
 80007d2:	9901      	ldr	r1, [sp, #4]
 80007d4:	1e4b      	subs	r3, r1, #1
 80007d6:	2b1f      	cmp	r3, #31
 80007d8:	f200 80ef 	bhi.w	80009ba <firewall_dispatch+0x3ea>
                rv = ERANGE;
            } else {
                if(pin_prefix_words((char *)buf_io, arg2, (uint32_t *)buf_io)) {
 80007dc:	462a      	mov	r2, r5
 80007de:	4628      	mov	r0, r5
 80007e0:	f002 fdcc 	bl	800337c <pin_prefix_words>
 80007e4:	e7e7      	b.n	80007b6 <firewall_dispatch+0x1e6>
            break;
        }

        case 17:
            // test rng
            REQUIRE_OUT(32);
 80007e6:	2300      	movs	r3, #0
 80007e8:	4632      	mov	r2, r6
 80007ea:	2120      	movs	r1, #32
 80007ec:	4628      	mov	r0, r5
 80007ee:	f7ff fdb9 	bl	8000364 <good_addr>
 80007f2:	4604      	mov	r4, r0
 80007f4:	2800      	cmp	r0, #0
 80007f6:	f040 80e9 	bne.w	80009cc <firewall_dispatch+0x3fc>
            memset(buf_io, 0x55, 32);       // to help show errors
 80007fa:	2220      	movs	r2, #32
 80007fc:	2155      	movs	r1, #85	; 0x55
 80007fe:	4628      	mov	r0, r5
 8000800:	f006 f878 	bl	80068f4 <memset>
            rng_buffer(buf_io, 32);
 8000804:	2120      	movs	r1, #32
 8000806:	4628      	mov	r0, r5
 8000808:	f001 fc0e 	bl	8002028 <rng_buffer>
            break;
 800080c:	e0de      	b.n	80009cc <firewall_dispatch+0x3fc>

        case 18: {
            // Try login w/ PIN.
            REQUIRE_OUT(sizeof(pinAttempt_t));
 800080e:	2300      	movs	r3, #0
 8000810:	4632      	mov	r2, r6
 8000812:	21f8      	movs	r1, #248	; 0xf8
 8000814:	4628      	mov	r0, r5
 8000816:	f7ff fda5 	bl	8000364 <good_addr>
 800081a:	4604      	mov	r4, r0
 800081c:	2800      	cmp	r0, #0
 800081e:	f040 80d5 	bne.w	80009cc <firewall_dispatch+0x3fc>
            pinAttempt_t *args = (pinAttempt_t *)buf_io;

            switch(arg2) {
 8000822:	9b01      	ldr	r3, [sp, #4]
 8000824:	2b05      	cmp	r3, #5
 8000826:	f200 80cc 	bhi.w	80009c2 <firewall_dispatch+0x3f2>
 800082a:	e8df f003 	tbb	[pc, r3]
 800082e:	0703      	.short	0x0703
 8000830:	17130f0b 	.word	0x17130f0b
                case 0:
                    rv = pin_setup_attempt(args);
 8000834:	4628      	mov	r0, r5
 8000836:	f002 fde3 	bl	8003400 <pin_setup_attempt>
 800083a:	e092      	b.n	8000962 <firewall_dispatch+0x392>
                    break;
                case 1:
                    rv = pin_delay(args);
 800083c:	4628      	mov	r0, r5
 800083e:	f002 fe63 	bl	8003508 <pin_delay>
 8000842:	e08e      	b.n	8000962 <firewall_dispatch+0x392>
                    break;
                case 2:
                    rv = pin_login_attempt(args);
 8000844:	4628      	mov	r0, r5
 8000846:	f002 fe75 	bl	8003534 <pin_login_attempt>
 800084a:	e08a      	b.n	8000962 <firewall_dispatch+0x392>
                    break;
                case 3:
                    rv = pin_change(args);
 800084c:	4628      	mov	r0, r5
 800084e:	f002 ff43 	bl	80036d8 <pin_change>
 8000852:	e086      	b.n	8000962 <firewall_dispatch+0x392>
                    break;
                case 4:
                    rv = pin_fetch_secret(args);
 8000854:	4628      	mov	r0, r5
 8000856:	f003 f849 	bl	80038ec <pin_fetch_secret>
 800085a:	e082      	b.n	8000962 <firewall_dispatch+0x392>
                    break;

                case 5:
                    rv = pin_firmware_greenlight(args);
 800085c:	4628      	mov	r0, r5
 800085e:	f003 f8cb 	bl	80039f8 <pin_firmware_greenlight>
 8000862:	e07e      	b.n	8000962 <firewall_dispatch+0x392>
            break;
        }


        case 19: {   // bag number stuff
            switch(arg2) {
 8000864:	9b01      	ldr	r3, [sp, #4]
 8000866:	2b64      	cmp	r3, #100	; 0x64
 8000868:	d044      	beq.n	80008f4 <firewall_dispatch+0x324>
 800086a:	d803      	bhi.n	8000874 <firewall_dispatch+0x2a4>
 800086c:	b14b      	cbz	r3, 8000882 <firewall_dispatch+0x2b2>
 800086e:	2b01      	cmp	r3, #1
 8000870:	d034      	beq.n	80008dc <firewall_dispatch+0x30c>
 8000872:	e0a6      	b.n	80009c2 <firewall_dispatch+0x3f2>
 8000874:	2b65      	cmp	r3, #101	; 0x65
 8000876:	d03f      	beq.n	80008f8 <firewall_dispatch+0x328>
 8000878:	2b66      	cmp	r3, #102	; 0x66
 800087a:	f040 80a2 	bne.w	80009c2 <firewall_dispatch+0x3f2>
                case 101:
                    flash_lockdown_hard(OB_RDP_LEVEL_1);        // Can only do 0->1 (experiments)
                    break;
                case 102:
                    // production units will be:
                    flash_lockdown_hard(OB_RDP_LEVEL_2);        // No change possible after this.
 800087e:	20cc      	movs	r0, #204	; 0xcc
 8000880:	e03b      	b.n	80008fa <firewall_dispatch+0x32a>

        case 19: {   // bag number stuff
            switch(arg2) {
                case 0:
                    // read out number
                    REQUIRE_OUT(32);
 8000882:	4632      	mov	r2, r6
 8000884:	2120      	movs	r1, #32
 8000886:	4628      	mov	r0, r5
 8000888:	f7ff fd6c 	bl	8000364 <good_addr>
 800088c:	4604      	mov	r4, r0
 800088e:	2800      	cmp	r0, #0
 8000890:	f040 809c 	bne.w	80009cc <firewall_dispatch+0x3fc>
                    memcpy(buf_io, rom_secrets->bag_number, 32);
 8000894:	4a0f      	ldr	r2, [pc, #60]	; (80008d4 <firewall_dispatch+0x304>)
 8000896:	4e10      	ldr	r6, [pc, #64]	; (80008d8 <firewall_dispatch+0x308>)
 8000898:	4613      	mov	r3, r2
 800089a:	cb03      	ldmia	r3!, {r0, r1}
 800089c:	42b3      	cmp	r3, r6
 800089e:	6028      	str	r0, [r5, #0]
 80008a0:	6069      	str	r1, [r5, #4]
 80008a2:	461a      	mov	r2, r3
 80008a4:	f105 0508 	add.w	r5, r5, #8
 80008a8:	d1f6      	bne.n	8000898 <firewall_dispatch+0x2c8>
 80008aa:	e08f      	b.n	80009cc <firewall_dispatch+0x3fc>
 80008ac:	40011c00 	.word	0x40011c00
 80008b0:	08007390 	.word	0x08007390
 80008b4:	40022000 	.word	0x40022000
 80008b8:	08006aa9 	.word	0x08006aa9
 80008bc:	08006cc3 	.word	0x08006cc3
 80008c0:	08006d5b 	.word	0x08006d5b
 80008c4:	08006f19 	.word	0x08006f19
 80008c8:	08006967 	.word	0x08006967
 80008cc:	20008000 	.word	0x20008000
 80008d0:	080069eb 	.word	0x080069eb
 80008d4:	08007850 	.word	0x08007850
 80008d8:	08007870 	.word	0x08007870
                    break;

                case 1:
                    // set the bag number, and (should) do lock down
                    REQUIRE_IN_ONLY(32);
 80008dc:	4632      	mov	r2, r6
 80008de:	2120      	movs	r1, #32
 80008e0:	4628      	mov	r0, r5
 80008e2:	f7ff fd3f 	bl	8000364 <good_addr>
 80008e6:	4604      	mov	r4, r0
 80008e8:	2800      	cmp	r0, #0
 80008ea:	d16f      	bne.n	80009cc <firewall_dispatch+0x3fc>

                    flash_save_bag_number(buf_io);
 80008ec:	4628      	mov	r0, r5
 80008ee:	f001 fa29 	bl	8001d44 <flash_save_bag_number>
                    break;
 80008f2:	e06b      	b.n	80009cc <firewall_dispatch+0x3fc>

                case 100:
                    flash_lockdown_hard(OB_RDP_LEVEL_0);        // wipes contents of flash (1->0)
 80008f4:	20aa      	movs	r0, #170	; 0xaa
 80008f6:	e000      	b.n	80008fa <firewall_dispatch+0x32a>
                    break;
                case 101:
                    flash_lockdown_hard(OB_RDP_LEVEL_1);        // Can only do 0->1 (experiments)
 80008f8:	20bb      	movs	r0, #187	; 0xbb
                    break;
                case 102:
                    // production units will be:
                    flash_lockdown_hard(OB_RDP_LEVEL_2);        // No change possible after this.
 80008fa:	f001 fab7 	bl	8001e6c <flash_lockdown_hard>
{

    // from linker, offset of firewall entry
    extern uint32_t firewall_starts;

    int rv = 0;
 80008fe:	2400      	movs	r4, #0
                    flash_lockdown_hard(OB_RDP_LEVEL_1);        // Can only do 0->1 (experiments)
                    break;
                case 102:
                    // production units will be:
                    flash_lockdown_hard(OB_RDP_LEVEL_2);        // No change possible after this.
                    break;
 8000900:	e064      	b.n	80009cc <firewall_dispatch+0x3fc>
        }
            

        case 20:
            // Read a single byte of config dataspace
            REQUIRE_OUT(1);
 8000902:	2300      	movs	r3, #0
 8000904:	4632      	mov	r2, r6
 8000906:	2101      	movs	r1, #1
 8000908:	4628      	mov	r0, r5
 800090a:	f7ff fd2b 	bl	8000364 <good_addr>
 800090e:	4604      	mov	r4, r0
 8000910:	2800      	cmp	r0, #0
 8000912:	d15b      	bne.n	80009cc <firewall_dispatch+0x3fc>

            rv = ae_read_config_byte(arg2 & 0x7f);
 8000914:	9801      	ldr	r0, [sp, #4]
 8000916:	f000 007f 	and.w	r0, r0, #127	; 0x7f
 800091a:	f002 fa41 	bl	8002da0 <ae_read_config_byte>
            if(rv == -1) {
 800091e:	1c43      	adds	r3, r0, #1
 8000920:	d04d      	beq.n	80009be <firewall_dispatch+0x3ee>
                rv = EIO;
            } else {
                buf_io[0] = rv;
 8000922:	7028      	strb	r0, [r5, #0]
 8000924:	e052      	b.n	80009cc <firewall_dispatch+0x3fc>
            } 
            break;

        case 21:
            // read OTP / downgrade protection
            switch(arg2) {
 8000926:	9b01      	ldr	r3, [sp, #4]
 8000928:	2b01      	cmp	r3, #1
 800092a:	d010      	beq.n	800094e <firewall_dispatch+0x37e>
 800092c:	d302      	bcc.n	8000934 <firewall_dispatch+0x364>
 800092e:	2b02      	cmp	r3, #2
 8000930:	d019      	beq.n	8000966 <firewall_dispatch+0x396>
 8000932:	e046      	b.n	80009c2 <firewall_dispatch+0x3f2>
                case 0:
                    REQUIRE_OUT(8);
 8000934:	2300      	movs	r3, #0
 8000936:	4632      	mov	r2, r6
 8000938:	2108      	movs	r1, #8
 800093a:	4628      	mov	r0, r5
 800093c:	f7ff fd12 	bl	8000364 <good_addr>
 8000940:	4604      	mov	r4, r0
 8000942:	2800      	cmp	r0, #0
 8000944:	d142      	bne.n	80009cc <firewall_dispatch+0x3fc>
                    get_min_version(buf_io);
 8000946:	4628      	mov	r0, r5
 8000948:	f000 ffbe 	bl	80018c8 <get_min_version>
                    break;
 800094c:	e03e      	b.n	80009cc <firewall_dispatch+0x3fc>

                case 1:
                    REQUIRE_IN_ONLY(8);
 800094e:	4632      	mov	r2, r6
 8000950:	2108      	movs	r1, #8
 8000952:	4628      	mov	r0, r5
 8000954:	f7ff fd06 	bl	8000364 <good_addr>
 8000958:	4604      	mov	r4, r0
 800095a:	bbb8      	cbnz	r0, 80009cc <firewall_dispatch+0x3fc>
                    rv = check_is_downgrade(buf_io);
 800095c:	4628      	mov	r0, r5
 800095e:	f000 ffd1 	bl	8001904 <check_is_downgrade>
 8000962:	4604      	mov	r4, r0
                    break;
 8000964:	e032      	b.n	80009cc <firewall_dispatch+0x3fc>

                case 2:
                    REQUIRE_IN_ONLY(8);
 8000966:	2301      	movs	r3, #1
 8000968:	4632      	mov	r2, r6
 800096a:	2108      	movs	r1, #8
 800096c:	4628      	mov	r0, r5
 800096e:	f7ff fcf9 	bl	8000364 <good_addr>
 8000972:	4604      	mov	r4, r0
 8000974:	bb50      	cbnz	r0, 80009cc <firewall_dispatch+0x3fc>

                    if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) {
 8000976:	782b      	ldrb	r3, [r5, #0]
 8000978:	3b10      	subs	r3, #16
                        // bad data
                        rv = ERANGE;
 800097a:	2b2f      	cmp	r3, #47	; 0x2f
                    } if(check_is_downgrade(buf_io)) {
 800097c:	4628      	mov	r0, r5
                case 2:
                    REQUIRE_IN_ONLY(8);

                    if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) {
                        // bad data
                        rv = ERANGE;
 800097e:	bf88      	it	hi
 8000980:	2422      	movhi	r4, #34	; 0x22
                    } if(check_is_downgrade(buf_io)) {
 8000982:	f000 ffbf 	bl	8001904 <check_is_downgrade>
 8000986:	b9f0      	cbnz	r0, 80009c6 <firewall_dispatch+0x3f6>
                        // already at a higher version?
                        rv = EAGAIN;
                    } else {
                        uint8_t min[8];
                        get_min_version(min);
 8000988:	a80c      	add	r0, sp, #48	; 0x30
 800098a:	f000 ff9d 	bl	80018c8 <get_min_version>

                        if(memcmp(min, buf_io, 8) == 0) {
 800098e:	2208      	movs	r2, #8
 8000990:	4629      	mov	r1, r5
 8000992:	a80c      	add	r0, sp, #48	; 0x30
 8000994:	f005 ff79 	bl	800688a <memcmp>
 8000998:	b1a8      	cbz	r0, 80009c6 <firewall_dispatch+0x3f6>
                            // dupe
                            rv = EAGAIN;
                        } else {
                            // save it, but might be "full" already
                            if(record_highwater_version(buf_io)) {
 800099a:	4628      	mov	r0, r5
 800099c:	f001 faaa 	bl	8001ef4 <record_highwater_version>
                                rv = ENOMEM;
 80009a0:	2800      	cmp	r0, #0
 80009a2:	bf18      	it	ne
 80009a4:	240c      	movne	r4, #12
 80009a6:	e011      	b.n	80009cc <firewall_dispatch+0x3fc>
            break;

        case -1:
            // System startup code. Cannot be reached by any code (that hopes to run
            // again) except our reset stub.
            if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) {
 80009a8:	f1b1 6f00 	cmp.w	r1, #134217728	; 0x8000000
 80009ac:	d90d      	bls.n	80009ca <firewall_dispatch+0x3fa>
 80009ae:	4b20      	ldr	r3, [pc, #128]	; (8000a30 <firewall_dispatch+0x460>)
 80009b0:	4299      	cmp	r1, r3
 80009b2:	d20a      	bcs.n	80009ca <firewall_dispatch+0x3fa>
                rv = EPERM;
            } else {
                system_startup();
 80009b4:	f7ff fdb8 	bl	8000528 <system_startup>
 80009b8:	e7a1      	b.n	80008fe <firewall_dispatch+0x32e>
    // - use arg2 use when a simple number is needed; never a pointer!
    // - mpy may provide a pointer to flash if we give it a qstr or small value, and if
    //   we're reading only, that's fine.

    if(len_in > 255) {
        rv = ERANGE;
 80009ba:	2422      	movs	r4, #34	; 0x22
 80009bc:	e006      	b.n	80009cc <firewall_dispatch+0x3fc>
            // Read a single byte of config dataspace
            REQUIRE_OUT(1);

            rv = ae_read_config_byte(arg2 & 0x7f);
            if(rv == -1) {
                rv = EIO;
 80009be:	2405      	movs	r4, #5
 80009c0:	e004      	b.n	80009cc <firewall_dispatch+0x3fc>
                        }
                    }
                    break;

                default:
                    rv = ENOENT;
 80009c2:	2402      	movs	r4, #2
 80009c4:	e002      	b.n	80009cc <firewall_dispatch+0x3fc>
                    if(buf_io[0] < 0x10 || buf_io[0] >= 0x40) {
                        // bad data
                        rv = ERANGE;
                    } if(check_is_downgrade(buf_io)) {
                        // already at a higher version?
                        rv = EAGAIN;
 80009c6:	240b      	movs	r4, #11
 80009c8:	e000      	b.n	80009cc <firewall_dispatch+0x3fc>

        case -1:
            // System startup code. Cannot be reached by any code (that hopes to run
            // again) except our reset stub.
            if(incoming_lr <= BL_FLASH_BASE || incoming_lr >= (uint32_t)&firewall_starts) {
                rv = EPERM;
 80009ca:	2401      	movs	r4, #1

fail:

    // Precaution: we don't want to leave ATECC508A authorized for any specific keys,
    // perhaps due to an error path we didn't see. Always reset the chip.
    ae_reset_chip();
 80009cc:	f001 fc62 	bl	8002294 <ae_reset_chip>

    // Unlikely it matters, but clear flash memory cache.
    __HAL_FLASH_DATA_CACHE_DISABLE();
 80009d0:	4b18      	ldr	r3, [pc, #96]	; (8000a34 <firewall_dispatch+0x464>)
 80009d2:	681a      	ldr	r2, [r3, #0]
 80009d4:	f422 6280 	bic.w	r2, r2, #1024	; 0x400
 80009d8:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_DATA_CACHE_RESET();
 80009da:	681a      	ldr	r2, [r3, #0]
 80009dc:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
 80009e0:	601a      	str	r2, [r3, #0]
 80009e2:	681a      	ldr	r2, [r3, #0]
 80009e4:	f422 5280 	bic.w	r2, r2, #4096	; 0x1000
 80009e8:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_DATA_CACHE_ENABLE();
 80009ea:	681a      	ldr	r2, [r3, #0]
 80009ec:	f442 6280 	orr.w	r2, r2, #1024	; 0x400
 80009f0:	601a      	str	r2, [r3, #0]

    // .. and instruction memory (flash cache too?)
    __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
 80009f2:	681a      	ldr	r2, [r3, #0]
 80009f4:	f422 7200 	bic.w	r2, r2, #512	; 0x200
 80009f8:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_INSTRUCTION_CACHE_RESET();
 80009fa:	681a      	ldr	r2, [r3, #0]
 80009fc:	f442 6200 	orr.w	r2, r2, #2048	; 0x800
 8000a00:	601a      	str	r2, [r3, #0]
 8000a02:	681a      	ldr	r2, [r3, #0]
 8000a04:	f422 6200 	bic.w	r2, r2, #2048	; 0x800
 8000a08:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
 8000a0a:	681a      	ldr	r2, [r3, #0]
 8000a0c:	f442 7200 	orr.w	r2, r2, #512	; 0x200
 8000a10:	601a      	str	r2, [r3, #0]
    

    // authorize return from firewall into user's code
    __HAL_FIREWALL_PREARM_ENABLE();
 8000a12:	f5a3 3382 	sub.w	r3, r3, #66560	; 0x10400

    return rv;
}
 8000a16:	4620      	mov	r0, r4
    __HAL_FLASH_INSTRUCTION_CACHE_RESET();
    __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
    

    // authorize return from firewall into user's code
    __HAL_FIREWALL_PREARM_ENABLE();
 8000a18:	6a1a      	ldr	r2, [r3, #32]
 8000a1a:	f042 0201 	orr.w	r2, r2, #1
 8000a1e:	621a      	str	r2, [r3, #32]
 8000a20:	6a1b      	ldr	r3, [r3, #32]
 8000a22:	f003 0301 	and.w	r3, r3, #1
 8000a26:	930c      	str	r3, [sp, #48]	; 0x30
 8000a28:	9b0c      	ldr	r3, [sp, #48]	; 0x30

    return rv;
}
 8000a2a:	b028      	add	sp, #160	; 0xa0
 8000a2c:	bd70      	pop	{r4, r5, r6, pc}
 8000a2e:	bf00      	nop
 8000a30:	08000300 	.word	0x08000300
 8000a34:	40022000 	.word	0x40022000

08000a38 <HAL_GetTick>:
const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \
                                  4000000, 8000000, 16000000, 24000000, 32000000, 48000000};
uint32_t SystemCoreClock;

// TODO: cleanup HAL stuff to not use this
uint32_t HAL_GetTick(void) { return 53; }
 8000a38:	2035      	movs	r0, #53	; 0x35
 8000a3a:	4770      	bx	lr

08000a3c <write_bytes>:
//
    static inline void
write_bytes(int len, const uint8_t *buf)
{
    // send via SPI(1)
    HAL_SPI_Transmit(&spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY);
 8000a3c:	b282      	uxth	r2, r0
 8000a3e:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8000a42:	4801      	ldr	r0, [pc, #4]	; (8000a48 <write_bytes+0xc>)
 8000a44:	f000 bbc1 	b.w	80011ca <HAL_SPI_Transmit>
 8000a48:	10006250 	.word	0x10006250

08000a4c <oled_write_cmd>:

// oled_write_cmd()
//
    void
oled_write_cmd(uint8_t cmd)
{
 8000a4c:	b513      	push	{r0, r1, r4, lr}
 8000a4e:	ac02      	add	r4, sp, #8
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000a50:	2201      	movs	r2, #1

// oled_write_cmd()
//
    void
oled_write_cmd(uint8_t cmd)
{
 8000a52:	f804 0d01 	strb.w	r0, [r4, #-1]!
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000a56:	2110      	movs	r1, #16
 8000a58:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000a5c:	f000 fb2a 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 0);
 8000a60:	2200      	movs	r2, #0
 8000a62:	f44f 7180 	mov.w	r1, #256	; 0x100
 8000a66:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000a6a:	f000 fb23 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
 8000a6e:	2200      	movs	r2, #0
 8000a70:	2110      	movs	r1, #16
 8000a72:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000a76:	f000 fb1d 	bl	80010b4 <HAL_GPIO_WritePin>

    write_bytes(1, &cmd);
 8000a7a:	4621      	mov	r1, r4
 8000a7c:	2001      	movs	r0, #1
 8000a7e:	f7ff ffdd 	bl	8000a3c <write_bytes>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000a82:	2201      	movs	r2, #1
 8000a84:	2110      	movs	r1, #16
 8000a86:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000a8a:	f000 fb13 	bl	80010b4 <HAL_GPIO_WritePin>
}
 8000a8e:	b002      	add	sp, #8
 8000a90:	bd10      	pop	{r4, pc}

08000a92 <oled_write_cmd_sequence>:

// oled_write_cmd_sequence()
//
    void
oled_write_cmd_sequence(int len, const uint8_t *cmds)
{
 8000a92:	b570      	push	{r4, r5, r6, lr}
 8000a94:	4606      	mov	r6, r0
 8000a96:	460d      	mov	r5, r1
    for(int i=0; i<len; i++) {
 8000a98:	460c      	mov	r4, r1
 8000a9a:	1b63      	subs	r3, r4, r5
 8000a9c:	429e      	cmp	r6, r3
 8000a9e:	dd04      	ble.n	8000aaa <oled_write_cmd_sequence+0x18>
        oled_write_cmd(cmds[i]);
 8000aa0:	f814 0b01 	ldrb.w	r0, [r4], #1
 8000aa4:	f7ff ffd2 	bl	8000a4c <oled_write_cmd>
 8000aa8:	e7f7      	b.n	8000a9a <oled_write_cmd_sequence+0x8>
    }
}
 8000aaa:	bd70      	pop	{r4, r5, r6, pc}

08000aac <oled_write_data>:

// oled_write_data()
//
    void
oled_write_data(int len, const uint8_t *pixels)
{
 8000aac:	b538      	push	{r3, r4, r5, lr}
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000aae:	2201      	movs	r2, #1

// oled_write_data()
//
    void
oled_write_data(int len, const uint8_t *pixels)
{
 8000ab0:	4604      	mov	r4, r0
 8000ab2:	460d      	mov	r5, r1
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000ab4:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000ab8:	2110      	movs	r1, #16
 8000aba:	f000 fafb 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
 8000abe:	2201      	movs	r2, #1
 8000ac0:	f44f 7180 	mov.w	r1, #256	; 0x100
 8000ac4:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000ac8:	f000 faf4 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
 8000acc:	2200      	movs	r2, #0
 8000ace:	2110      	movs	r1, #16
 8000ad0:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000ad4:	f000 faee 	bl	80010b4 <HAL_GPIO_WritePin>

    write_bytes(len, pixels);
 8000ad8:	4629      	mov	r1, r5
 8000ada:	4620      	mov	r0, r4
 8000adc:	f7ff ffae 	bl	8000a3c <write_bytes>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000ae0:	2201      	movs	r2, #1
 8000ae2:	2110      	movs	r1, #16
 8000ae4:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
}
 8000ae8:	e8bd 4038 	ldmia.w	sp!, {r3, r4, r5, lr}
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);

    write_bytes(len, pixels);

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000aec:	f000 bae2 	b.w	80010b4 <HAL_GPIO_WritePin>

08000af0 <oled_setup>:
//
// Ok to call this lots.
//
    void
oled_setup(void)
{
 8000af0:	b530      	push	{r4, r5, lr}
    static uint32_t inited;

    if(inited == 0x238a572F) {
 8000af2:	4b35      	ldr	r3, [pc, #212]	; (8000bc8 <oled_setup+0xd8>)
 8000af4:	4a35      	ldr	r2, [pc, #212]	; (8000bcc <oled_setup+0xdc>)
 8000af6:	6819      	ldr	r1, [r3, #0]
 8000af8:	4291      	cmp	r1, r2
//
// Ok to call this lots.
//
    void
oled_setup(void)
{
 8000afa:	b089      	sub	sp, #36	; 0x24
    static uint32_t inited;

    if(inited == 0x238a572F) {
 8000afc:	d062      	beq.n	8000bc4 <oled_setup+0xd4>
        return;
    }
    inited = 0x238a572F;
 8000afe:	601a      	str	r2, [r3, #0]

    // enable some internal clocks
    __HAL_RCC_GPIOA_CLK_ENABLE();
 8000b00:	4b33      	ldr	r3, [pc, #204]	; (8000bd0 <oled_setup+0xe0>)
    __HAL_RCC_SPI1_CLK_ENABLE();

    // simple pins
    GPIO_InitTypeDef setup = {
 8000b02:	4d34      	ldr	r5, [pc, #208]	; (8000bd4 <oled_setup+0xe4>)
        return;
    }
    inited = 0x238a572F;

    // enable some internal clocks
    __HAL_RCC_GPIOA_CLK_ENABLE();
 8000b04:	6cda      	ldr	r2, [r3, #76]	; 0x4c
 8000b06:	f042 0201 	orr.w	r2, r2, #1
 8000b0a:	64da      	str	r2, [r3, #76]	; 0x4c
 8000b0c:	6cda      	ldr	r2, [r3, #76]	; 0x4c
 8000b0e:	f002 0201 	and.w	r2, r2, #1
 8000b12:	9201      	str	r2, [sp, #4]
 8000b14:	9a01      	ldr	r2, [sp, #4]
    __HAL_RCC_SPI1_CLK_ENABLE();
 8000b16:	6e1a      	ldr	r2, [r3, #96]	; 0x60
 8000b18:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
 8000b1c:	661a      	str	r2, [r3, #96]	; 0x60
 8000b1e:	6e1b      	ldr	r3, [r3, #96]	; 0x60
 8000b20:	f403 5380 	and.w	r3, r3, #4096	; 0x1000
 8000b24:	9302      	str	r3, [sp, #8]
 8000b26:	9b02      	ldr	r3, [sp, #8]

    // simple pins
    GPIO_InitTypeDef setup = {
 8000b28:	cd0f      	ldmia	r5!, {r0, r1, r2, r3}
 8000b2a:	ac03      	add	r4, sp, #12
 8000b2c:	c40f      	stmia	r4!, {r0, r1, r2, r3}
 8000b2e:	682b      	ldr	r3, [r5, #0]
 8000b30:	6023      	str	r3, [r4, #0]
        .Mode = GPIO_MODE_OUTPUT_PP,
        .Pull = GPIO_NOPULL,
        .Speed = GPIO_SPEED_FREQ_MEDIUM,
        .Alternate = 0,
    };
    HAL_GPIO_Init(GPIOA, &setup);
 8000b32:	a903      	add	r1, sp, #12
 8000b34:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000b38:	f000 f93e 	bl	8000db8 <HAL_GPIO_Init>

    // starting values
    HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1);
 8000b3c:	2201      	movs	r2, #1
 8000b3e:	f44f 71a8 	mov.w	r1, #336	; 0x150
 8000b42:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000b46:	f000 fab5 	bl	80010b4 <HAL_GPIO_WritePin>

    // SPI pins
    setup.Pin = SPI_SCK | SPI_MOSI;
 8000b4a:	23a0      	movs	r3, #160	; 0xa0
 8000b4c:	9303      	str	r3, [sp, #12]
    setup.Mode = GPIO_MODE_AF_PP;
 8000b4e:	2302      	movs	r3, #2
 8000b50:	9304      	str	r3, [sp, #16]
    setup.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &setup);
 8000b52:	a903      	add	r1, sp, #12
    HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1);

    // SPI pins
    setup.Pin = SPI_SCK | SPI_MOSI;
    setup.Mode = GPIO_MODE_AF_PP;
    setup.Alternate = GPIO_AF5_SPI1;
 8000b54:	2305      	movs	r3, #5
    HAL_GPIO_Init(GPIOA, &setup);
 8000b56:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
    HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1);

    // SPI pins
    setup.Pin = SPI_SCK | SPI_MOSI;
    setup.Mode = GPIO_MODE_AF_PP;
    setup.Alternate = GPIO_AF5_SPI1;
 8000b5a:	9307      	str	r3, [sp, #28]
    HAL_GPIO_Init(GPIOA, &setup);
 8000b5c:	f000 f92c 	bl	8000db8 <HAL_GPIO_Init>

    // lock the RESET pin so that St's DFU code doesn't clear screen
    // it might be trying to use it a MISO signal for SPI loading
    HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN);
 8000b60:	f44f 71a8 	mov.w	r1, #336	; 0x150
 8000b64:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000b68:	f000 faad 	bl	80010c6 <HAL_GPIO_LockPin>

    // 10ms low-going pulse on reset pin
    delay_ms(1);
 8000b6c:	2001      	movs	r0, #1
 8000b6e:	f002 fa5d 	bl	800302c <delay_ms>
    HAL_GPIO_WritePin(GPIOA, RESET_PIN, 0);
 8000b72:	2200      	movs	r2, #0
 8000b74:	2140      	movs	r1, #64	; 0x40
 8000b76:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
    delay_ms(10);
    HAL_GPIO_WritePin(GPIOA, RESET_PIN, 1);

    memset(&spi_port, 0, sizeof(spi_port));
 8000b7a:	4c17      	ldr	r4, [pc, #92]	; (8000bd8 <oled_setup+0xe8>)
    // it might be trying to use it a MISO signal for SPI loading
    HAL_GPIO_LockPin(GPIOA, RESET_PIN | CS_PIN | DC_PIN);

    // 10ms low-going pulse on reset pin
    delay_ms(1);
    HAL_GPIO_WritePin(GPIOA, RESET_PIN, 0);
 8000b7c:	f000 fa9a 	bl	80010b4 <HAL_GPIO_WritePin>
    delay_ms(10);
 8000b80:	200a      	movs	r0, #10
 8000b82:	f002 fa53 	bl	800302c <delay_ms>
    HAL_GPIO_WritePin(GPIOA, RESET_PIN, 1);
 8000b86:	2201      	movs	r2, #1
 8000b88:	2140      	movs	r1, #64	; 0x40
 8000b8a:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000b8e:	f000 fa91 	bl	80010b4 <HAL_GPIO_WritePin>

    memset(&spi_port, 0, sizeof(spi_port));
 8000b92:	2100      	movs	r1, #0
 8000b94:	2264      	movs	r2, #100	; 0x64
 8000b96:	4620      	mov	r0, r4
 8000b98:	f005 feac 	bl	80068f4 <memset>

    spi_port.Instance = SPI1;

    // see SPI_InitTypeDef
    spi_port.Init.Mode = SPI_MODE_MASTER;
 8000b9c:	4a0f      	ldr	r2, [pc, #60]	; (8000bdc <oled_setup+0xec>)
 8000b9e:	f44f 7382 	mov.w	r3, #260	; 0x104
 8000ba2:	e884 000c 	stmia.w	r4, {r2, r3}
    spi_port.Init.Direction = SPI_DIRECTION_2LINES;
    spi_port.Init.DataSize = SPI_DATASIZE_8BIT;
 8000ba6:	f44f 63e0 	mov.w	r3, #1792	; 0x700
 8000baa:	60e3      	str	r3, [r4, #12]
    spi_port.Init.CLKPolarity = SPI_POLARITY_LOW;
    spi_port.Init.CLKPhase = SPI_PHASE_1EDGE;
    spi_port.Init.NSS = SPI_NSS_SOFT;
 8000bac:	f44f 7300 	mov.w	r3, #512	; 0x200
 8000bb0:	61a3      	str	r3, [r4, #24]
    spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;    // conservative
    spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB;
    spi_port.Init.TIMode = SPI_TIMODE_DISABLED;
    spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    HAL_SPI_Init(&spi_port);
 8000bb2:	4620      	mov	r0, r4
    spi_port.Init.Direction = SPI_DIRECTION_2LINES;
    spi_port.Init.DataSize = SPI_DATASIZE_8BIT;
    spi_port.Init.CLKPolarity = SPI_POLARITY_LOW;
    spi_port.Init.CLKPhase = SPI_PHASE_1EDGE;
    spi_port.Init.NSS = SPI_NSS_SOFT;
    spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;    // conservative
 8000bb4:	2318      	movs	r3, #24
 8000bb6:	61e3      	str	r3, [r4, #28]
    spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB;
    spi_port.Init.TIMode = SPI_TIMODE_DISABLED;
    spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    HAL_SPI_Init(&spi_port);
 8000bb8:	f000 fac0 	bl	800113c <HAL_SPI_Init>
    // this code:
    //      '0x37c', '0x1700', '0x603'
    //SPI1->CR1 = 0x354;

    // write a sequence to reset things
    oled_write_cmd_sequence(sizeof(reset_commands), reset_commands);
 8000bbc:	4908      	ldr	r1, [pc, #32]	; (8000be0 <oled_setup+0xf0>)
 8000bbe:	2019      	movs	r0, #25
 8000bc0:	f7ff ff67 	bl	8000a92 <oled_write_cmd_sequence>
}
 8000bc4:	b009      	add	sp, #36	; 0x24
 8000bc6:	bd30      	pop	{r4, r5, pc}
 8000bc8:	1000624c 	.word	0x1000624c
 8000bcc:	238a572f 	.word	0x238a572f
 8000bd0:	40021000 	.word	0x40021000
 8000bd4:	080069b8 	.word	0x080069b8
 8000bd8:	10006250 	.word	0x10006250
 8000bdc:	40013000 	.word	0x40013000
 8000be0:	080069d2 	.word	0x080069d2

08000be4 <oled_show_raw>:
//
// No decompression.
//
    void
oled_show_raw(uint32_t len, const uint8_t *pixels)
{
 8000be4:	b538      	push	{r3, r4, r5, lr}
 8000be6:	4604      	mov	r4, r0
 8000be8:	460d      	mov	r5, r1
    oled_setup();
 8000bea:	f7ff ff81 	bl	8000af0 <oled_setup>

    oled_write_cmd_sequence(sizeof(before_show), before_show);
 8000bee:	4911      	ldr	r1, [pc, #68]	; (8000c34 <oled_show_raw+0x50>)
 8000bf0:	2006      	movs	r0, #6
 8000bf2:	f7ff ff4e 	bl	8000a92 <oled_write_cmd_sequence>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000bf6:	2201      	movs	r2, #1
 8000bf8:	2110      	movs	r1, #16
 8000bfa:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000bfe:	f000 fa59 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
 8000c02:	2201      	movs	r2, #1
 8000c04:	f44f 7180 	mov.w	r1, #256	; 0x100
 8000c08:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000c0c:	f000 fa52 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
 8000c10:	2200      	movs	r2, #0
 8000c12:	2110      	movs	r1, #16
 8000c14:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000c18:	f000 fa4c 	bl	80010b4 <HAL_GPIO_WritePin>

    write_bytes(len, pixels);
 8000c1c:	4629      	mov	r1, r5
 8000c1e:	4620      	mov	r0, r4
 8000c20:	f7ff ff0c 	bl	8000a3c <write_bytes>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000c24:	2201      	movs	r2, #1
 8000c26:	2110      	movs	r1, #16
 8000c28:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
}
 8000c2c:	e8bd 4038 	ldmia.w	sp!, {r3, r4, r5, lr}
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);

    write_bytes(len, pixels);

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000c30:	f000 ba40 	b.w	80010b4 <HAL_GPIO_WritePin>
 8000c34:	080069cc 	.word	0x080069cc

08000c38 <oled_show>:
//
// Perform simple RLE decompression.
//
    void
oled_show(const uint8_t *pixels)
{
 8000c38:	b530      	push	{r4, r5, lr}
 8000c3a:	b0a1      	sub	sp, #132	; 0x84
 8000c3c:	4604      	mov	r4, r0
    oled_setup();
 8000c3e:	f7ff ff57 	bl	8000af0 <oled_setup>

    oled_write_cmd_sequence(sizeof(before_show), before_show);
 8000c42:	491c      	ldr	r1, [pc, #112]	; (8000cb4 <oled_show+0x7c>)
 8000c44:	2006      	movs	r0, #6
 8000c46:	f7ff ff24 	bl	8000a92 <oled_write_cmd_sequence>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000c4a:	2201      	movs	r2, #1
 8000c4c:	2110      	movs	r1, #16
 8000c4e:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000c52:	f000 fa2f 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
 8000c56:	2201      	movs	r2, #1
 8000c58:	f44f 7180 	mov.w	r1, #256	; 0x100
 8000c5c:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000c60:	f000 fa28 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
 8000c64:	2200      	movs	r2, #0
 8000c66:	2110      	movs	r1, #16
 8000c68:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000c6c:	f000 fa22 	bl	80010b4 <HAL_GPIO_WritePin>
    uint8_t         buf[127];
    const uint8_t *p = pixels;

    // NOTE: must also update code in oled_show_progress, which dups this heavily.
    while(1) {
        uint8_t hdr = *(p++);
 8000c70:	7823      	ldrb	r3, [r4, #0]
        if(!hdr) break;
 8000c72:	b1b3      	cbz	r3, 8000ca2 <oled_show+0x6a>

        uint8_t len = hdr & 0x7f;
 8000c74:	f003 057f 	and.w	r5, r3, #127	; 0x7f
        if(hdr & 0x80) {
 8000c78:	061b      	lsls	r3, r3, #24
 8000c7a:	d507      	bpl.n	8000c8c <oled_show+0x54>
    uint8_t         buf[127];
    const uint8_t *p = pixels;

    // NOTE: must also update code in oled_show_progress, which dups this heavily.
    while(1) {
        uint8_t hdr = *(p++);
 8000c7c:	3401      	adds	r4, #1
        if(!hdr) break;

        uint8_t len = hdr & 0x7f;
        if(hdr & 0x80) {
            // random bytes follow
            memcpy(buf, p, len);
 8000c7e:	4621      	mov	r1, r4
 8000c80:	462a      	mov	r2, r5
 8000c82:	4668      	mov	r0, sp
 8000c84:	f005 fe10 	bl	80068a8 <memcpy>
            p += len;
 8000c88:	442c      	add	r4, r5
 8000c8a:	e005      	b.n	8000c98 <oled_show+0x60>
        } else {
            // repeat same byte
            memset(buf, *p, len);
 8000c8c:	7861      	ldrb	r1, [r4, #1]
 8000c8e:	462a      	mov	r2, r5
 8000c90:	4668      	mov	r0, sp
 8000c92:	f005 fe2f 	bl	80068f4 <memset>
            p++;
 8000c96:	3402      	adds	r4, #2
        }

        write_bytes(len, buf);
 8000c98:	4669      	mov	r1, sp
 8000c9a:	4628      	mov	r0, r5
 8000c9c:	f7ff fece 	bl	8000a3c <write_bytes>
    }
 8000ca0:	e7e6      	b.n	8000c70 <oled_show+0x38>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000ca2:	2201      	movs	r2, #1
 8000ca4:	2110      	movs	r1, #16
 8000ca6:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000caa:	f000 fa03 	bl	80010b4 <HAL_GPIO_WritePin>
}
 8000cae:	b021      	add	sp, #132	; 0x84
 8000cb0:	bd30      	pop	{r4, r5, pc}
 8000cb2:	bf00      	nop
 8000cb4:	080069cc 	.word	0x080069cc

08000cb8 <oled_show_progress>:
//
// Perform simple RLE decompression, and add a bar on final screen line.
//
    void
oled_show_progress(const uint8_t *pixels, int progress)
{
 8000cb8:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
 8000cbc:	b0a0      	sub	sp, #128	; 0x80
 8000cbe:	460d      	mov	r5, r1
 8000cc0:	4607      	mov	r7, r0
    oled_setup();
 8000cc2:	f7ff ff15 	bl	8000af0 <oled_setup>

    oled_write_cmd_sequence(sizeof(before_show), before_show);
 8000cc6:	493b      	ldr	r1, [pc, #236]	; (8000db4 <oled_show_progress+0xfc>)
 8000cc8:	2006      	movs	r0, #6
 8000cca:	f7ff fee2 	bl	8000a92 <oled_write_cmd_sequence>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000cce:	2201      	movs	r2, #1
 8000cd0:	2110      	movs	r1, #16
 8000cd2:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000cd6:	f000 f9ed 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, DC_PIN, 1);
 8000cda:	2201      	movs	r2, #1
 8000cdc:	f44f 7180 	mov.w	r1, #256	; 0x100
 8000ce0:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000ce4:	f000 f9e6 	bl	80010b4 <HAL_GPIO_WritePin>
    HAL_GPIO_WritePin(GPIOA, CS_PIN, 0);
 8000ce8:	2110      	movs	r1, #16
 8000cea:	2200      	movs	r2, #0
 8000cec:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000cf0:	f000 f9e0 	bl	80010b4 <HAL_GPIO_WritePin>

    uint8_t         buf[127];
    const uint8_t *p = pixels;

    const uint16_t p_start = 896;
    uint32_t p_count = 1280 * progress / 1000;
 8000cf4:	f44f 61a0 	mov.w	r1, #1280	; 0x500
 8000cf8:	4369      	muls	r1, r5
 8000cfa:	2600      	movs	r6, #0
 8000cfc:	f44f 757a 	mov.w	r5, #1000	; 0x3e8
 8000d00:	fb91 f5f5 	sdiv	r5, r1, r5
 8000d04:	2d80      	cmp	r5, #128	; 0x80
 8000d06:	bf28      	it	cs
 8000d08:	2580      	movcs	r5, #128	; 0x80
 8000d0a:	46b0      	mov	r8, r6

    bool last_line = false;

    uint16_t offset = 0;
    while(1) {
        uint8_t hdr = *(p++);
 8000d0c:	783b      	ldrb	r3, [r7, #0]
        if(hdr == 0) break;
 8000d0e:	b3ab      	cbz	r3, 8000d7c <oled_show_progress+0xc4>

        uint8_t len = hdr & 0x7f;
 8000d10:	f003 047f 	and.w	r4, r3, #127	; 0x7f
        if(hdr & 0x80) {
 8000d14:	061b      	lsls	r3, r3, #24
 8000d16:	d507      	bpl.n	8000d28 <oled_show_progress+0x70>

    bool last_line = false;

    uint16_t offset = 0;
    while(1) {
        uint8_t hdr = *(p++);
 8000d18:	3701      	adds	r7, #1
        if(hdr == 0) break;

        uint8_t len = hdr & 0x7f;
        if(hdr & 0x80) {
            // random bytes follow
            memcpy(buf, p, len);
 8000d1a:	4639      	mov	r1, r7
 8000d1c:	4622      	mov	r2, r4
 8000d1e:	4668      	mov	r0, sp
 8000d20:	f005 fdc2 	bl	80068a8 <memcpy>
            p += len;
 8000d24:	4427      	add	r7, r4
 8000d26:	e005      	b.n	8000d34 <oled_show_progress+0x7c>
        } else {
            // repeat same byte
            memset(buf, *p, len);
 8000d28:	7879      	ldrb	r1, [r7, #1]
 8000d2a:	4622      	mov	r2, r4
 8000d2c:	4668      	mov	r0, sp
 8000d2e:	f005 fde1 	bl	80068f4 <memset>
            p++;
 8000d32:	3702      	adds	r7, #2
        }

        if(!last_line && (offset+len) >= p_start) {
 8000d34:	f1b8 0f00 	cmp.w	r8, #0
 8000d38:	d129      	bne.n	8000d8e <oled_show_progress+0xd6>
 8000d3a:	1933      	adds	r3, r6, r4
 8000d3c:	f5b3 7f60 	cmp.w	r3, #896	; 0x380
 8000d40:	db15      	blt.n	8000d6e <oled_show_progress+0xb6>
            last_line = true;

            // adjust so we're aligned w/ last line
            int h = p_start - offset;
            if(h) {
 8000d42:	f5d6 7860 	rsbs	r8, r6, #896	; 0x380
 8000d46:	d022      	beq.n	8000d8e <oled_show_progress+0xd6>
                write_bytes(h, buf);
 8000d48:	4669      	mov	r1, sp
 8000d4a:	4640      	mov	r0, r8
                memmove(buf, buf+h, len-h);
 8000d4c:	ebc8 0404 	rsb	r4, r8, r4
            last_line = true;

            // adjust so we're aligned w/ last line
            int h = p_start - offset;
            if(h) {
                write_bytes(h, buf);
 8000d50:	f7ff fe74 	bl	8000a3c <write_bytes>
                memmove(buf, buf+h, len-h);
 8000d54:	4622      	mov	r2, r4
 8000d56:	eb0d 0108 	add.w	r1, sp, r8
 8000d5a:	4668      	mov	r0, sp
 8000d5c:	f005 fdaf 	bl	80068be <memmove>
                len -= h;
 8000d60:	b2e4      	uxtb	r4, r4
                offset += h;
 8000d62:	f44f 7660 	mov.w	r6, #896	; 0x380
 8000d66:	e012      	b.n	8000d8e <oled_show_progress+0xd6>
 8000d68:	4615      	mov	r5, r2
 8000d6a:	f04f 0801 	mov.w	r8, #1
            for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
                buf[j] |= 0x80;
            }
        }

        write_bytes(len, buf);
 8000d6e:	4669      	mov	r1, sp
 8000d70:	4620      	mov	r0, r4
        offset += len;
 8000d72:	4426      	add	r6, r4
            for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
                buf[j] |= 0x80;
            }
        }

        write_bytes(len, buf);
 8000d74:	f7ff fe62 	bl	8000a3c <write_bytes>
        offset += len;
 8000d78:	b2b6      	uxth	r6, r6
    }
 8000d7a:	e7c7      	b.n	8000d0c <oled_show_progress+0x54>

    HAL_GPIO_WritePin(GPIOA, CS_PIN, 1);
 8000d7c:	2201      	movs	r2, #1
 8000d7e:	2110      	movs	r1, #16
 8000d80:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 8000d84:	f000 f996 	bl	80010b4 <HAL_GPIO_WritePin>
}
 8000d88:	b020      	add	sp, #128	; 0x80
 8000d8a:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

    uint8_t         buf[127];
    const uint8_t *p = pixels;

    const uint16_t p_start = 896;
    uint32_t p_count = 1280 * progress / 1000;
 8000d8e:	2300      	movs	r3, #0
                offset += h;
            }
        }

        if(last_line) {
            for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
 8000d90:	42ab      	cmp	r3, r5
 8000d92:	eba5 0203 	sub.w	r2, r5, r3
 8000d96:	d009      	beq.n	8000dac <oled_show_progress+0xf4>
 8000d98:	42a3      	cmp	r3, r4
 8000d9a:	dae5      	bge.n	8000d68 <oled_show_progress+0xb0>
                buf[j] |= 0x80;
 8000d9c:	f81d 2003 	ldrb.w	r2, [sp, r3]
 8000da0:	f062 027f 	orn	r2, r2, #127	; 0x7f
 8000da4:	f80d 2003 	strb.w	r2, [sp, r3]
                offset += h;
            }
        }

        if(last_line) {
            for(int j=0; (p_count > 0) && (j<len); j++, p_count--) {
 8000da8:	3301      	adds	r3, #1
 8000daa:	e7f1      	b.n	8000d90 <oled_show_progress+0xd8>
 8000dac:	f04f 0801 	mov.w	r8, #1
 8000db0:	2500      	movs	r5, #0
 8000db2:	e7dc      	b.n	8000d6e <oled_show_progress+0xb6>
 8000db4:	080069cc 	.word	0x080069cc

08000db8 <HAL_GPIO_Init>:
  * @param  GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
 8000db8:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
  assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
  assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
  assert_param(IS_GPIO_PULL(GPIO_Init->Pull));

  /* Configure the port pins */
  while (((GPIO_Init->Pin) >> position) != RESET)
 8000dbc:	f8d1 b000 	ldr.w	fp, [r1]
      /*--------------------- EXTI Mode Configuration ------------------------*/
      /* Configure the External Interrupt or event for the current IO */
      if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
      {
        /* Enable SYSCFG Clock */
        __HAL_RCC_SYSCFG_CLK_ENABLE();
 8000dc0:	f8df 81ac 	ldr.w	r8, [pc, #428]	; 8000f70 <HAL_GPIO_Init+0x1b8>
 8000dc4:	4c68      	ldr	r4, [pc, #416]	; (8000f68 <HAL_GPIO_Init+0x1b0>)
  * @param  GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
  *         the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
{
 8000dc6:	b085      	sub	sp, #20
  uint32_t position = 0x00;
 8000dc8:	2300      	movs	r3, #0
  assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
  assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
  assert_param(IS_GPIO_PULL(GPIO_Init->Pull));

  /* Configure the port pins */
  while (((GPIO_Init->Pin) >> position) != RESET)
 8000dca:	fa3b f203 	lsrs.w	r2, fp, r3
 8000dce:	f000 80c7 	beq.w	8000f60 <HAL_GPIO_Init+0x1a8>
  {
    /* Get current io position */
    iocurrent = (GPIO_Init->Pin) & (1U << position);
 8000dd2:	2601      	movs	r6, #1
 8000dd4:	409e      	lsls	r6, r3

    if(iocurrent)
 8000dd6:	ea1b 0e06 	ands.w	lr, fp, r6
 8000dda:	f000 80bf 	beq.w	8000f5c <HAL_GPIO_Init+0x1a4>
    {
      /*--------------------- GPIO Mode Configuration ------------------------*/
      /* In case of Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_AF_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
 8000dde:	684a      	ldr	r2, [r1, #4]
 8000de0:	f022 0910 	bic.w	r9, r2, #16
 8000de4:	f1b9 0f02 	cmp.w	r9, #2
 8000de8:	d114      	bne.n	8000e14 <HAL_GPIO_Init+0x5c>
 8000dea:	ea4f 0cd3 	mov.w	ip, r3, lsr #3
 8000dee:	eb00 0c8c 	add.w	ip, r0, ip, lsl #2
        assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));

        /* Configure Alternate function mapped with the current IO */
        temp = GPIOx->AFR[position >> 3];
        temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
 8000df2:	f003 0a07 	and.w	sl, r3, #7
        /* Check the Alternate function parameters */
        assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
        assert_param(IS_GPIO_AF(GPIO_Init->Alternate));

        /* Configure Alternate function mapped with the current IO */
        temp = GPIOx->AFR[position >> 3];
 8000df6:	f8dc 7020 	ldr.w	r7, [ip, #32]
        temp &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
 8000dfa:	ea4f 0a8a 	mov.w	sl, sl, lsl #2
 8000dfe:	250f      	movs	r5, #15
 8000e00:	fa05 f50a 	lsl.w	r5, r5, sl
 8000e04:	ea27 0705 	bic.w	r7, r7, r5
        temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
 8000e08:	690d      	ldr	r5, [r1, #16]
 8000e0a:	fa05 f50a 	lsl.w	r5, r5, sl
 8000e0e:	433d      	orrs	r5, r7
        GPIOx->AFR[position >> 3] = temp;
 8000e10:	f8cc 5020 	str.w	r5, [ip, #32]
 8000e14:	ea4f 0c43 	mov.w	ip, r3, lsl #1
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
      temp &= ~(GPIO_MODER_MODE0 << (position * 2));
 8000e18:	2503      	movs	r5, #3
        temp |= ((uint32_t)(GPIO_Init->Alternate) << (((uint32_t)position & (uint32_t)0x07) * 4));
        GPIOx->AFR[position >> 3] = temp;
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
 8000e1a:	6807      	ldr	r7, [r0, #0]
      temp &= ~(GPIO_MODER_MODE0 << (position * 2));
 8000e1c:	fa05 f50c 	lsl.w	r5, r5, ip
 8000e20:	43ed      	mvns	r5, r5
      temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
 8000e22:	f002 0a03 	and.w	sl, r2, #3
        GPIOx->AFR[position >> 3] = temp;
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
      temp &= ~(GPIO_MODER_MODE0 << (position * 2));
 8000e26:	9501      	str	r5, [sp, #4]
      temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
      GPIOx->MODER = temp;

      /* In case of Output or Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
 8000e28:	f109 39ff 	add.w	r9, r9, #4294967295	; 0xffffffff
        GPIOx->AFR[position >> 3] = temp;
      }

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
      temp &= ~(GPIO_MODER_MODE0 << (position * 2));
 8000e2c:	403d      	ands	r5, r7
      temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
 8000e2e:	fa0a f70c 	lsl.w	r7, sl, ip
 8000e32:	433d      	orrs	r5, r7
      GPIOx->MODER = temp;

      /* In case of Output or Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
 8000e34:	f1b9 0f01 	cmp.w	r9, #1

      /* Configure IO Direction mode (Input, Output, Alternate or Analog) */
      temp = GPIOx->MODER;
      temp &= ~(GPIO_MODER_MODE0 << (position * 2));
      temp |= ((GPIO_Init->Mode & GPIO_MODE) << (position * 2));
      GPIOx->MODER = temp;
 8000e38:	6005      	str	r5, [r0, #0]

      /* In case of Output or Alternate function mode selection */
      if((GPIO_Init->Mode == GPIO_MODE_OUTPUT_PP) || (GPIO_Init->Mode == GPIO_MODE_AF_PP) ||
 8000e3a:	d813      	bhi.n	8000e64 <HAL_GPIO_Init+0xac>
         (GPIO_Init->Mode == GPIO_MODE_OUTPUT_OD) || (GPIO_Init->Mode == GPIO_MODE_AF_OD))
      {
        /* Check the Speed parameter */
        assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
        /* Configure the IO Speed */
        temp = GPIOx->OSPEEDR;
 8000e3c:	6887      	ldr	r7, [r0, #8]
        temp &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
 8000e3e:	9d01      	ldr	r5, [sp, #4]
 8000e40:	ea05 0907 	and.w	r9, r5, r7
        temp |= (GPIO_Init->Speed << (position * 2));
 8000e44:	68cf      	ldr	r7, [r1, #12]
 8000e46:	fa07 f70c 	lsl.w	r7, r7, ip
 8000e4a:	ea47 0709 	orr.w	r7, r7, r9
        GPIOx->OSPEEDR = temp;
 8000e4e:	6087      	str	r7, [r0, #8]

        /* Configure the IO Output Type */
        temp = GPIOx->OTYPER;
 8000e50:	6847      	ldr	r7, [r0, #4]
        temp &= ~(GPIO_OTYPER_OT0 << position) ;
        temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
 8000e52:	f3c2 1900 	ubfx	r9, r2, #4, #1
        temp |= (GPIO_Init->Speed << (position * 2));
        GPIOx->OSPEEDR = temp;

        /* Configure the IO Output Type */
        temp = GPIOx->OTYPER;
        temp &= ~(GPIO_OTYPER_OT0 << position) ;
 8000e56:	ea27 0706 	bic.w	r7, r7, r6
        temp |= (((GPIO_Init->Mode & GPIO_OUTPUT_TYPE) >> 4) << position);
 8000e5a:	fa09 f903 	lsl.w	r9, r9, r3
 8000e5e:	ea49 0707 	orr.w	r7, r9, r7
        GPIOx->OTYPER = temp;
 8000e62:	6047      	str	r7, [r0, #4]
      }

#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)

      /* In case of Analog mode, check if ADC control mode is selected */
      if((GPIO_Init->Mode & GPIO_MODE_ANALOG) == GPIO_MODE_ANALOG)
 8000e64:	f1ba 0f03 	cmp.w	sl, #3
 8000e68:	d107      	bne.n	8000e7a <HAL_GPIO_Init+0xc2>
      {
        /* Configure the IO Output Type */
        temp = GPIOx->ASCR;
 8000e6a:	6ac7      	ldr	r7, [r0, #44]	; 0x2c
        temp &= ~(GPIO_ASCR_ASC0 << position) ;
 8000e6c:	ea27 0606 	bic.w	r6, r7, r6
        temp |= (((GPIO_Init->Mode & ANALOG_MODE) >> 3) << position);
 8000e70:	f3c2 07c0 	ubfx	r7, r2, #3, #1
 8000e74:	409f      	lsls	r7, r3
 8000e76:	433e      	orrs	r6, r7
        GPIOx->ASCR = temp;
 8000e78:	62c6      	str	r6, [r0, #44]	; 0x2c
      }

#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */

      /* Activate the Pull-up or Pull down resistor for the current IO */
      temp = GPIOx->PUPDR;
 8000e7a:	68c6      	ldr	r6, [r0, #12]
      temp &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
 8000e7c:	9d01      	ldr	r5, [sp, #4]
 8000e7e:	4035      	ands	r5, r6
      temp |= ((GPIO_Init->Pull) << (position * 2));
 8000e80:	688e      	ldr	r6, [r1, #8]
 8000e82:	fa06 f60c 	lsl.w	r6, r6, ip
 8000e86:	4335      	orrs	r5, r6
      GPIOx->PUPDR = temp;
 8000e88:	60c5      	str	r5, [r0, #12]

      /*--------------------- EXTI Mode Configuration ------------------------*/
      /* Configure the External Interrupt or event for the current IO */
      if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
 8000e8a:	00d5      	lsls	r5, r2, #3
 8000e8c:	d566      	bpl.n	8000f5c <HAL_GPIO_Init+0x1a4>
      {
        /* Enable SYSCFG Clock */
        __HAL_RCC_SYSCFG_CLK_ENABLE();
 8000e8e:	f8d8 5060 	ldr.w	r5, [r8, #96]	; 0x60
 8000e92:	f045 0501 	orr.w	r5, r5, #1
 8000e96:	f8c8 5060 	str.w	r5, [r8, #96]	; 0x60
 8000e9a:	f8d8 5060 	ldr.w	r5, [r8, #96]	; 0x60
 8000e9e:	f023 0703 	bic.w	r7, r3, #3
 8000ea2:	f107 4780 	add.w	r7, r7, #1073741824	; 0x40000000
 8000ea6:	f005 0501 	and.w	r5, r5, #1
 8000eaa:	f507 3780 	add.w	r7, r7, #65536	; 0x10000
 8000eae:	9503      	str	r5, [sp, #12]

        temp = SYSCFG->EXTICR[position >> 2];
        temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
 8000eb0:	f003 0c03 	and.w	ip, r3, #3
      /*--------------------- EXTI Mode Configuration ------------------------*/
      /* Configure the External Interrupt or event for the current IO */
      if((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
      {
        /* Enable SYSCFG Clock */
        __HAL_RCC_SYSCFG_CLK_ENABLE();
 8000eb4:	9d03      	ldr	r5, [sp, #12]

        temp = SYSCFG->EXTICR[position >> 2];
 8000eb6:	68be      	ldr	r6, [r7, #8]
        temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
 8000eb8:	ea4f 0c8c 	mov.w	ip, ip, lsl #2
 8000ebc:	250f      	movs	r5, #15
 8000ebe:	fa05 f50c 	lsl.w	r5, r5, ip
        temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
 8000ec2:	f1b0 4f90 	cmp.w	r0, #1207959552	; 0x48000000
      {
        /* Enable SYSCFG Clock */
        __HAL_RCC_SYSCFG_CLK_ENABLE();

        temp = SYSCFG->EXTICR[position >> 2];
        temp &= ~(((uint32_t)0x0F) << (4 * (position & 0x03)));
 8000ec6:	ea26 0605 	bic.w	r6, r6, r5
        temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
 8000eca:	d019      	beq.n	8000f00 <HAL_GPIO_Init+0x148>
 8000ecc:	4d27      	ldr	r5, [pc, #156]	; (8000f6c <HAL_GPIO_Init+0x1b4>)
 8000ece:	42a8      	cmp	r0, r5
 8000ed0:	d018      	beq.n	8000f04 <HAL_GPIO_Init+0x14c>
 8000ed2:	f505 6580 	add.w	r5, r5, #1024	; 0x400
 8000ed6:	42a8      	cmp	r0, r5
 8000ed8:	d016      	beq.n	8000f08 <HAL_GPIO_Init+0x150>
 8000eda:	f505 6580 	add.w	r5, r5, #1024	; 0x400
 8000ede:	42a8      	cmp	r0, r5
 8000ee0:	d014      	beq.n	8000f0c <HAL_GPIO_Init+0x154>
 8000ee2:	f505 6580 	add.w	r5, r5, #1024	; 0x400
 8000ee6:	42a8      	cmp	r0, r5
 8000ee8:	d012      	beq.n	8000f10 <HAL_GPIO_Init+0x158>
 8000eea:	f505 6580 	add.w	r5, r5, #1024	; 0x400
 8000eee:	42a8      	cmp	r0, r5
 8000ef0:	d010      	beq.n	8000f14 <HAL_GPIO_Init+0x15c>
 8000ef2:	f505 6580 	add.w	r5, r5, #1024	; 0x400
 8000ef6:	42a8      	cmp	r0, r5
 8000ef8:	bf14      	ite	ne
 8000efa:	2507      	movne	r5, #7
 8000efc:	2506      	moveq	r5, #6
 8000efe:	e00a      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f00:	2500      	movs	r5, #0
 8000f02:	e008      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f04:	2501      	movs	r5, #1
 8000f06:	e006      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f08:	2502      	movs	r5, #2
 8000f0a:	e004      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f0c:	2503      	movs	r5, #3
 8000f0e:	e002      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f10:	2504      	movs	r5, #4
 8000f12:	e000      	b.n	8000f16 <HAL_GPIO_Init+0x15e>
 8000f14:	2505      	movs	r5, #5
 8000f16:	fa05 f50c 	lsl.w	r5, r5, ip
 8000f1a:	4335      	orrs	r5, r6
        SYSCFG->EXTICR[position >> 2] = temp;
 8000f1c:	60bd      	str	r5, [r7, #8]

        /* Clear EXTI line configuration */
        temp = EXTI->IMR1;
 8000f1e:	4d12      	ldr	r5, [pc, #72]	; (8000f68 <HAL_GPIO_Init+0x1b0>)
 8000f20:	682d      	ldr	r5, [r5, #0]
        temp &= ~((uint32_t)iocurrent);
 8000f22:	ea6f 060e 	mvn.w	r6, lr
        if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
 8000f26:	03d7      	lsls	r7, r2, #15
        temp |= (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03)));
        SYSCFG->EXTICR[position >> 2] = temp;

        /* Clear EXTI line configuration */
        temp = EXTI->IMR1;
        temp &= ~((uint32_t)iocurrent);
 8000f28:	bf54      	ite	pl
 8000f2a:	4035      	andpl	r5, r6
        if((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
        {
          temp |= iocurrent;
 8000f2c:	ea4e 0505 	orrmi.w	r5, lr, r5
        }
        EXTI->IMR1 = temp;
 8000f30:	6025      	str	r5, [r4, #0]

        temp = EXTI->EMR1;
 8000f32:	6865      	ldr	r5, [r4, #4]
        temp &= ~((uint32_t)iocurrent);
        if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
 8000f34:	0397      	lsls	r7, r2, #14
          temp |= iocurrent;
        }
        EXTI->IMR1 = temp;

        temp = EXTI->EMR1;
        temp &= ~((uint32_t)iocurrent);
 8000f36:	bf54      	ite	pl
 8000f38:	4035      	andpl	r5, r6
        if((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
        {
          temp |= iocurrent;
 8000f3a:	ea4e 0505 	orrmi.w	r5, lr, r5
        }
        EXTI->EMR1 = temp;
 8000f3e:	6065      	str	r5, [r4, #4]

        /* Clear Rising Falling edge configuration */
        temp = EXTI->RTSR1;
 8000f40:	68a5      	ldr	r5, [r4, #8]
        temp &= ~((uint32_t)iocurrent);
        if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
 8000f42:	02d7      	lsls	r7, r2, #11
        }
        EXTI->EMR1 = temp;

        /* Clear Rising Falling edge configuration */
        temp = EXTI->RTSR1;
        temp &= ~((uint32_t)iocurrent);
 8000f44:	bf54      	ite	pl
 8000f46:	4035      	andpl	r5, r6
        if((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
        {
          temp |= iocurrent;
 8000f48:	ea4e 0505 	orrmi.w	r5, lr, r5
        }
        EXTI->RTSR1 = temp;
 8000f4c:	60a5      	str	r5, [r4, #8]

        temp = EXTI->FTSR1;
 8000f4e:	68e5      	ldr	r5, [r4, #12]
        temp &= ~((uint32_t)iocurrent);
        if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
 8000f50:	0292      	lsls	r2, r2, #10
          temp |= iocurrent;
        }
        EXTI->RTSR1 = temp;

        temp = EXTI->FTSR1;
        temp &= ~((uint32_t)iocurrent);
 8000f52:	bf54      	ite	pl
 8000f54:	4035      	andpl	r5, r6
        if((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
        {
          temp |= iocurrent;
 8000f56:	ea4e 0505 	orrmi.w	r5, lr, r5
        }
        EXTI->FTSR1 = temp;
 8000f5a:	60e5      	str	r5, [r4, #12]
      }
    }

    position++;
 8000f5c:	3301      	adds	r3, #1
 8000f5e:	e734      	b.n	8000dca <HAL_GPIO_Init+0x12>
  }
}
 8000f60:	b005      	add	sp, #20
 8000f62:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 8000f66:	bf00      	nop
 8000f68:	40010400 	.word	0x40010400
 8000f6c:	48000400 	.word	0x48000400
 8000f70:	40021000 	.word	0x40021000

08000f74 <HAL_GPIO_DeInit>:
  * @param  GPIO_Pin: specifies the port bit to be written.
  *         This parameter can be one of GPIO_PIN_x where x can be (0..15).
  * @retval None
  */
void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
{
 8000f74:	e92d 4ff7 	stmdb	sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, sl, fp, lr}
      {
        tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
        SYSCFG->EXTICR[position >> 2] &= ~tmp;

        /* Clear EXTI line configuration */
        EXTI->IMR1 &= ~((uint32_t)iocurrent);
 8000f78:	4a47      	ldr	r2, [pc, #284]	; (8001098 <HAL_GPIO_DeInit+0x124>)
      /*------------------------- EXTI Mode Configuration --------------------*/
      /* Clear the External Interrupt or Event for the current IO */

      tmp = SYSCFG->EXTICR[position >> 2];
      tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
      if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
 8000f7a:	f8df a124 	ldr.w	sl, [pc, #292]	; 80010a0 <HAL_GPIO_DeInit+0x12c>
 8000f7e:	f8df b124 	ldr.w	fp, [pc, #292]	; 80010a4 <HAL_GPIO_DeInit+0x130>
  *         This parameter can be one of GPIO_PIN_x where x can be (0..15).
  * @retval None
  */
void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)
{
  uint32_t position = 0x00;
 8000f82:	2300      	movs	r3, #0

  /* Configure the port pins */
  while ((GPIO_Pin >> position) != RESET)
  {
    /* Get current io position */
    iocurrent = (GPIO_Pin) & (1U << position);
 8000f84:	f04f 0801 	mov.w	r8, #1

    if (iocurrent)
    {
      /*------------------------- GPIO Mode Configuration --------------------*/
      /* Configure IO in Analog Mode */
      GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2));
 8000f88:	f04f 0903 	mov.w	r9, #3
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  /* Configure the port pins */
  while ((GPIO_Pin >> position) != RESET)
 8000f8c:	fa31 f403 	lsrs.w	r4, r1, r3
 8000f90:	d07e      	beq.n	8001090 <HAL_GPIO_DeInit+0x11c>
  {
    /* Get current io position */
    iocurrent = (GPIO_Pin) & (1U << position);
 8000f92:	fa08 f603 	lsl.w	r6, r8, r3

    if (iocurrent)
 8000f96:	ea11 0406 	ands.w	r4, r1, r6
 8000f9a:	9401      	str	r4, [sp, #4]
 8000f9c:	d076      	beq.n	800108c <HAL_GPIO_DeInit+0x118>
    {
      /*------------------------- GPIO Mode Configuration --------------------*/
      /* Configure IO in Analog Mode */
      GPIOx->MODER |= (GPIO_MODER_MODE0 << (position * 2));
 8000f9e:	6807      	ldr	r7, [r0, #0]
 8000fa0:	005c      	lsls	r4, r3, #1
 8000fa2:	fa09 f404 	lsl.w	r4, r9, r4
 8000fa6:	ea4f 0cd3 	mov.w	ip, r3, lsr #3
 8000faa:	4327      	orrs	r7, r4
 8000fac:	eb00 0c8c 	add.w	ip, r0, ip, lsl #2
 8000fb0:	6007      	str	r7, [r0, #0]

      /* Configure the default Alternate Function in current IO */
      GPIOx->AFR[position >> 3] &= ~((uint32_t)0xF << ((uint32_t)(position & (uint32_t)0x07) * 4)) ;
 8000fb2:	f8dc 7020 	ldr.w	r7, [ip, #32]
 8000fb6:	f003 0e07 	and.w	lr, r3, #7
 8000fba:	463d      	mov	r5, r7
 8000fbc:	ea4f 0e8e 	mov.w	lr, lr, lsl #2
 8000fc0:	270f      	movs	r7, #15
 8000fc2:	fa07 fe0e 	lsl.w	lr, r7, lr
 8000fc6:	ea25 0e0e 	bic.w	lr, r5, lr
 8000fca:	f8cc e020 	str.w	lr, [ip, #32]

      /* Configure the default value for IO Speed */
      GPIOx->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEED0 << (position * 2));
 8000fce:	f8d0 e008 	ldr.w	lr, [r0, #8]
 8000fd2:	43e4      	mvns	r4, r4
 8000fd4:	ea0e 0e04 	and.w	lr, lr, r4
 8000fd8:	f8c0 e008 	str.w	lr, [r0, #8]

      /* Configure the default value IO Output Type */
      GPIOx->OTYPER  &= ~(GPIO_OTYPER_OT0 << position) ;
 8000fdc:	f8d0 e004 	ldr.w	lr, [r0, #4]
 8000fe0:	43f6      	mvns	r6, r6
 8000fe2:	ea0e 0e06 	and.w	lr, lr, r6
 8000fe6:	f8c0 e004 	str.w	lr, [r0, #4]

      /* Deactivate the Pull-up and Pull-down resistor for the current IO */
      GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPD0 << (position * 2));
 8000fea:	f8d0 e00c 	ldr.w	lr, [r0, #12]
 8000fee:	ea04 040e 	and.w	r4, r4, lr
 8000ff2:	60c4      	str	r4, [r0, #12]

#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)

      /* Deactivate the Control bit of Analog mode for the current IO */
      GPIOx->ASCR &= ~(GPIO_ASCR_ASC0<< position);
 8000ff4:	6ac4      	ldr	r4, [r0, #44]	; 0x2c
 8000ff6:	4026      	ands	r6, r4
 8000ff8:	62c6      	str	r6, [r0, #44]	; 0x2c
 8000ffa:	f023 0603 	bic.w	r6, r3, #3
 8000ffe:	f106 4680 	add.w	r6, r6, #1073741824	; 0x40000000
 8001002:	f506 3680 	add.w	r6, r6, #65536	; 0x10000

      /*------------------------- EXTI Mode Configuration --------------------*/
      /* Clear the External Interrupt or Event for the current IO */

      tmp = SYSCFG->EXTICR[position >> 2];
      tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
 8001006:	f003 0e03 	and.w	lr, r3, #3
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx */

      /*------------------------- EXTI Mode Configuration --------------------*/
      /* Clear the External Interrupt or Event for the current IO */

      tmp = SYSCFG->EXTICR[position >> 2];
 800100a:	68b4      	ldr	r4, [r6, #8]
      tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
 800100c:	ea4f 0e8e 	mov.w	lr, lr, lsl #2
 8001010:	fa07 f70e 	lsl.w	r7, r7, lr
      if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
 8001014:	f1b0 4f90 	cmp.w	r0, #1207959552	; 0x48000000

      /*------------------------- EXTI Mode Configuration --------------------*/
      /* Clear the External Interrupt or Event for the current IO */

      tmp = SYSCFG->EXTICR[position >> 2];
      tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
 8001018:	ea04 0c07 	and.w	ip, r4, r7
      if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
 800101c:	d015      	beq.n	800104a <HAL_GPIO_DeInit+0xd6>
 800101e:	4c1f      	ldr	r4, [pc, #124]	; (800109c <HAL_GPIO_DeInit+0x128>)
 8001020:	42a0      	cmp	r0, r4
 8001022:	d014      	beq.n	800104e <HAL_GPIO_DeInit+0xda>
 8001024:	f504 6480 	add.w	r4, r4, #1024	; 0x400
 8001028:	42a0      	cmp	r0, r4
 800102a:	d012      	beq.n	8001052 <HAL_GPIO_DeInit+0xde>
 800102c:	f504 6480 	add.w	r4, r4, #1024	; 0x400
 8001030:	42a0      	cmp	r0, r4
 8001032:	d010      	beq.n	8001056 <HAL_GPIO_DeInit+0xe2>
 8001034:	f504 6480 	add.w	r4, r4, #1024	; 0x400
 8001038:	42a0      	cmp	r0, r4
 800103a:	d00e      	beq.n	800105a <HAL_GPIO_DeInit+0xe6>
 800103c:	4550      	cmp	r0, sl
 800103e:	d00e      	beq.n	800105e <HAL_GPIO_DeInit+0xea>
 8001040:	4558      	cmp	r0, fp
 8001042:	bf0c      	ite	eq
 8001044:	2406      	moveq	r4, #6
 8001046:	2407      	movne	r4, #7
 8001048:	e00a      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 800104a:	2400      	movs	r4, #0
 800104c:	e008      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 800104e:	2401      	movs	r4, #1
 8001050:	e006      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 8001052:	2402      	movs	r4, #2
 8001054:	e004      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 8001056:	2403      	movs	r4, #3
 8001058:	e002      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 800105a:	2404      	movs	r4, #4
 800105c:	e000      	b.n	8001060 <HAL_GPIO_DeInit+0xec>
 800105e:	2405      	movs	r4, #5
 8001060:	fa04 f40e 	lsl.w	r4, r4, lr
 8001064:	45a4      	cmp	ip, r4
 8001066:	d111      	bne.n	800108c <HAL_GPIO_DeInit+0x118>
      {
        tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
        SYSCFG->EXTICR[position >> 2] &= ~tmp;
 8001068:	68b4      	ldr	r4, [r6, #8]

        /* Clear EXTI line configuration */
        EXTI->IMR1 &= ~((uint32_t)iocurrent);
 800106a:	9d01      	ldr	r5, [sp, #4]
      tmp = SYSCFG->EXTICR[position >> 2];
      tmp &= (((uint32_t)0x0F) << (4 * (position & 0x03)));
      if(tmp == (GPIO_GET_INDEX(GPIOx) << (4 * (position & 0x03))))
      {
        tmp = ((uint32_t)0x0F) << (4 * (position & 0x03));
        SYSCFG->EXTICR[position >> 2] &= ~tmp;
 800106c:	ea24 0707 	bic.w	r7, r4, r7
 8001070:	60b7      	str	r7, [r6, #8]

        /* Clear EXTI line configuration */
        EXTI->IMR1 &= ~((uint32_t)iocurrent);
 8001072:	6814      	ldr	r4, [r2, #0]
 8001074:	43ed      	mvns	r5, r5
 8001076:	402c      	ands	r4, r5
 8001078:	6014      	str	r4, [r2, #0]
        EXTI->EMR1 &= ~((uint32_t)iocurrent);
 800107a:	6854      	ldr	r4, [r2, #4]
 800107c:	402c      	ands	r4, r5
 800107e:	6054      	str	r4, [r2, #4]

        /* Clear Rising Falling edge configuration */
        EXTI->RTSR1 &= ~((uint32_t)iocurrent);
 8001080:	6894      	ldr	r4, [r2, #8]
 8001082:	402c      	ands	r4, r5
 8001084:	6094      	str	r4, [r2, #8]
        EXTI->FTSR1 &= ~((uint32_t)iocurrent);
 8001086:	68d4      	ldr	r4, [r2, #12]
 8001088:	4025      	ands	r5, r4
 800108a:	60d5      	str	r5, [r2, #12]
      }
    }

    position++;
 800108c:	3301      	adds	r3, #1
 800108e:	e77d      	b.n	8000f8c <HAL_GPIO_DeInit+0x18>
  }
}
 8001090:	b003      	add	sp, #12
 8001092:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 8001096:	bf00      	nop
 8001098:	40010400 	.word	0x40010400
 800109c:	48000400 	.word	0x48000400
 80010a0:	48001400 	.word	0x48001400
 80010a4:	48001800 	.word	0x48001800

080010a8 <HAL_GPIO_ReadPin>:
  GPIO_PinState bitstatus;

  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  if((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
 80010a8:	6903      	ldr	r3, [r0, #16]
  }
  else
  {
    bitstatus = GPIO_PIN_RESET;
  }
  return bitstatus;
 80010aa:	4219      	tst	r1, r3
}
 80010ac:	bf14      	ite	ne
 80010ae:	2001      	movne	r0, #1
 80010b0:	2000      	moveq	r0, #0
 80010b2:	4770      	bx	lr

080010b4 <HAL_GPIO_WritePin>:
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_PIN_ACTION(PinState));

  if(PinState != GPIO_PIN_RESET)
 80010b4:	b10a      	cbz	r2, 80010ba <HAL_GPIO_WritePin+0x6>
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin;
 80010b6:	6181      	str	r1, [r0, #24]
 80010b8:	4770      	bx	lr
  }
  else
  {
    GPIOx->BRR = (uint32_t)GPIO_Pin;
 80010ba:	6281      	str	r1, [r0, #40]	; 0x28
 80010bc:	4770      	bx	lr

080010be <HAL_GPIO_TogglePin>:
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  GPIOx->ODR ^= GPIO_Pin;
 80010be:	6943      	ldr	r3, [r0, #20]
 80010c0:	4059      	eors	r1, r3
 80010c2:	6141      	str	r1, [r0, #20]
 80010c4:	4770      	bx	lr

080010c6 <HAL_GPIO_LockPin>:
  * @param  GPIO_Pin: specifies the port bits to be locked.
  *         This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  * @retval None
  */
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
 80010c6:	b082      	sub	sp, #8
  __IO uint32_t tmp = GPIO_LCKR_LCKK;
 80010c8:	f44f 3380 	mov.w	r3, #65536	; 0x10000
 80010cc:	9301      	str	r3, [sp, #4]
  /* Check the parameters */
  assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  /* Apply lock key write sequence */
  tmp |= GPIO_Pin;
 80010ce:	9b01      	ldr	r3, [sp, #4]
 80010d0:	430b      	orrs	r3, r1
 80010d2:	9301      	str	r3, [sp, #4]
  /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
  GPIOx->LCKR = tmp;
 80010d4:	9b01      	ldr	r3, [sp, #4]
 80010d6:	61c3      	str	r3, [r0, #28]
  /* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
  GPIOx->LCKR = GPIO_Pin;
 80010d8:	61c1      	str	r1, [r0, #28]
  /* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
  GPIOx->LCKR = tmp;
 80010da:	9b01      	ldr	r3, [sp, #4]
 80010dc:	61c3      	str	r3, [r0, #28]
  /* Read LCKK bit*/
  tmp = GPIOx->LCKR;
 80010de:	69c3      	ldr	r3, [r0, #28]
 80010e0:	9301      	str	r3, [sp, #4]

  if((GPIOx->LCKR & GPIO_LCKR_LCKK) != RESET)
 80010e2:	69c0      	ldr	r0, [r0, #28]
 80010e4:	f480 3080 	eor.w	r0, r0, #65536	; 0x10000
  }
  else
  {
    return HAL_ERROR;
  }
}
 80010e8:	f3c0 4000 	ubfx	r0, r0, #16, #1
 80010ec:	b002      	add	sp, #8
 80010ee:	4770      	bx	lr

080010f0 <HAL_GPIO_EXTI_Callback>:
  * @brief  EXTI line detection callback.
  * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
 80010f0:	4770      	bx	lr
	...

080010f4 <HAL_GPIO_EXTI_IRQHandler>:
  * @brief  Handle EXTI interrupt request.
  * @param  GPIO_Pin: Specifies the port pin connected to corresponding EXTI line.
  * @retval None
  */
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
 80010f4:	b508      	push	{r3, lr}
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
 80010f6:	4b04      	ldr	r3, [pc, #16]	; (8001108 <HAL_GPIO_EXTI_IRQHandler+0x14>)
 80010f8:	6959      	ldr	r1, [r3, #20]
 80010fa:	4201      	tst	r1, r0
 80010fc:	d002      	beq.n	8001104 <HAL_GPIO_EXTI_IRQHandler+0x10>
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
 80010fe:	6158      	str	r0, [r3, #20]
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
 8001100:	f7ff fff6 	bl	80010f0 <HAL_GPIO_EXTI_Callback>
 8001104:	bd08      	pop	{r3, pc}
 8001106:	bf00      	nop
 8001108:	40010400 	.word	0x40010400

0800110c <SPI_EndRxTxTransaction.isra.2>:
static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  __IO uint8_t tmpreg;

  while ((hspi->Instance->SR & Fifo) != State)
 800110c:	6803      	ldr	r3, [r0, #0]
  * @param  hspi: SPI handle
  * @param  Timeout: Timeout duration
  * @param  Tickstart: tick start value
  * @retval HAL status
  */
static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
 800110e:	b082      	sub	sp, #8
static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  __IO uint8_t tmpreg;

  while ((hspi->Instance->SR & Fifo) != State)
 8001110:	689a      	ldr	r2, [r3, #8]
 8001112:	f412 5fc0 	tst.w	r2, #6144	; 0x1800
 8001116:	d1fb      	bne.n	8001110 <SPI_EndRxTxTransaction.isra.2+0x4>
  * @retval HAL status
  */
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
 8001118:	689a      	ldr	r2, [r3, #8]
 800111a:	f002 0280 	and.w	r2, r2, #128	; 0x80
 800111e:	2a00      	cmp	r2, #0
 8001120:	d1fa      	bne.n	8001118 <SPI_EndRxTxTransaction.isra.2+0xc>
static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  __IO uint8_t tmpreg;

  while ((hspi->Instance->SR & Fifo) != State)
 8001122:	6898      	ldr	r0, [r3, #8]
 8001124:	f410 60c0 	ands.w	r0, r0, #1536	; 0x600
 8001128:	d006      	beq.n	8001138 <SPI_EndRxTxTransaction.isra.2+0x2c>
  {
    if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY))
    {
      tmpreg = *((__IO uint8_t *)&hspi->Instance->DR);
 800112a:	7b1a      	ldrb	r2, [r3, #12]
 800112c:	b2d2      	uxtb	r2, r2
 800112e:	f88d 2007 	strb.w	r2, [sp, #7]
      /* To avoid GCC warning */
      UNUSED(tmpreg);
 8001132:	f89d 2007 	ldrb.w	r2, [sp, #7]
 8001136:	e7f4      	b.n	8001122 <SPI_EndRxTxTransaction.isra.2+0x16>
  {
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
    return HAL_TIMEOUT;
  }
  return HAL_OK;
}
 8001138:	b002      	add	sp, #8
 800113a:	4770      	bx	lr

0800113c <HAL_SPI_Init>:
  * @param  hspi: pointer to a SPI_HandleTypeDef structure that contains
  *               the configuration information for SPI module.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
{
 800113c:	b570      	push	{r4, r5, r6, lr}
  uint32_t frxth;

  /* Check the SPI handle allocation */
  if (hspi == NULL)
 800113e:	2800      	cmp	r0, #0
 8001140:	d041      	beq.n	80011c6 <HAL_SPI_Init+0x8a>
  {
    assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
    assert_param(IS_SPI_CRC_LENGTH(hspi->Init.CRCLength));
  }
#else
  hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 8001142:	2300      	movs	r3, #0
 8001144:	6283      	str	r3, [r0, #40]	; 0x28
#endif /* USE_SPI_CRC */

  if (hspi->State == HAL_SPI_STATE_RESET)
 8001146:	f890 305d 	ldrb.w	r3, [r0, #93]	; 0x5d
 800114a:	f003 02ff 	and.w	r2, r3, #255	; 0xff
 800114e:	b90b      	cbnz	r3, 8001154 <HAL_SPI_Init+0x18>
  {
    /* Allocate lock resource and initialize it */
    hspi->Lock = HAL_UNLOCKED;
 8001150:	f880 205c 	strb.w	r2, [r0, #92]	; 0x5c
  }

  hspi->State = HAL_SPI_STATE_BUSY;

  /* Disable the selected SPI peripheral */
  __HAL_SPI_DISABLE(hspi);
 8001154:	6801      	ldr	r1, [r0, #0]

  /* Align by default the rs fifo threshold on the data size */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 8001156:	68c5      	ldr	r5, [r0, #12]

    /* Init the low level hardware : GPIO, CLOCK, NVIC... */
//PDG//    HAL_SPI_MspInit(hspi);
  }

  hspi->State = HAL_SPI_STATE_BUSY;
 8001158:	2202      	movs	r2, #2
 800115a:	f880 205d 	strb.w	r2, [r0, #93]	; 0x5d

  /* Disable the selected SPI peripheral */
  __HAL_SPI_DISABLE(hspi);
 800115e:	680b      	ldr	r3, [r1, #0]
 8001160:	f023 0340 	bic.w	r3, r3, #64	; 0x40
 8001164:	600b      	str	r3, [r1, #0]
    /* CRC must be disabled */
    hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  }

  /* Align the CRC Length on the data size */
  if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
 8001166:	6b03      	ldr	r3, [r0, #48]	; 0x30
  {
    frxth = SPI_RXFIFO_THRESHOLD_HF;
  }
  else
  {
    frxth = SPI_RXFIFO_THRESHOLD_QF;
 8001168:	f5b5 6fe0 	cmp.w	r5, #1792	; 0x700
 800116c:	bf8c      	ite	hi
 800116e:	2400      	movhi	r4, #0
 8001170:	f44f 5480 	movls.w	r4, #4096	; 0x1000
    /* CRC must be disabled */
    hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  }

  /* Align the CRC Length on the data size */
  if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
 8001174:	b92b      	cbnz	r3, 8001182 <HAL_SPI_Init+0x46>
  {
    /* CRC Length aligned on the data size : value set by default */
    if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 8001176:	f5b5 6fe0 	cmp.w	r5, #1792	; 0x700
    {
      hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
    }
    else
    {
      hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
 800117a:	bf96      	itet	ls
 800117c:	2301      	movls	r3, #1
  if (hspi->Init.CRCLength == SPI_CRC_LENGTH_DATASIZE)
  {
    /* CRC Length aligned on the data size : value set by default */
    if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
    {
      hspi->Init.CRCLength = SPI_CRC_LENGTH_16BIT;
 800117e:	6302      	strhi	r2, [r0, #48]	; 0x30
    }
    else
    {
      hspi->Init.CRCLength = SPI_CRC_LENGTH_8BIT;
 8001180:	6303      	strls	r3, [r0, #48]	; 0x30
  }

  /*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
  /* Configure : SPI Mode, Communication Mode, Clock polarity and phase, NSS management,
  Communication speed, First bit and CRC calculation state */
  WRITE_REG(hspi->Instance->CR1, (hspi->Init.Mode | hspi->Init.Direction |
 8001182:	6882      	ldr	r2, [r0, #8]
 8001184:	6846      	ldr	r6, [r0, #4]
 8001186:	6983      	ldr	r3, [r0, #24]
 8001188:	4316      	orrs	r6, r2
 800118a:	6902      	ldr	r2, [r0, #16]
 800118c:	4316      	orrs	r6, r2
 800118e:	6942      	ldr	r2, [r0, #20]
 8001190:	4316      	orrs	r6, r2
 8001192:	69c2      	ldr	r2, [r0, #28]
 8001194:	4316      	orrs	r6, r2
 8001196:	6a02      	ldr	r2, [r0, #32]
 8001198:	4316      	orrs	r6, r2
 800119a:	f403 7200 	and.w	r2, r3, #512	; 0x200
 800119e:	4332      	orrs	r2, r6
 80011a0:	600a      	str	r2, [r1, #0]
    hspi->Instance->CR1 |= SPI_CR1_CRCL;
  }
#endif /* USE_SPI_CRC */

  /* Configure : NSS management, TI Mode, NSS Pulse, Data size and Rx Fifo Threshold */
  WRITE_REG(hspi->Instance->CR2, (((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE) | hspi->Init.TIMode |
 80011a2:	6a42      	ldr	r2, [r0, #36]	; 0x24
 80011a4:	4315      	orrs	r5, r2
 80011a6:	6b42      	ldr	r2, [r0, #52]	; 0x34
 80011a8:	0c1b      	lsrs	r3, r3, #16
 80011aa:	4315      	orrs	r5, r2
 80011ac:	f003 0204 	and.w	r2, r3, #4
 80011b0:	ea45 0302 	orr.w	r3, r5, r2
 80011b4:	4323      	orrs	r3, r4
 80011b6:	604b      	str	r3, [r1, #4]
  /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
  CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
#endif /* SPI_I2SCFGR_I2SMOD */

  hspi->ErrorCode = HAL_SPI_ERROR_NONE;
  hspi->State     = HAL_SPI_STATE_READY;
 80011b8:	2201      	movs	r2, #1
#if defined(SPI_I2SCFGR_I2SMOD)
  /* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
  CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
#endif /* SPI_I2SCFGR_I2SMOD */

  hspi->ErrorCode = HAL_SPI_ERROR_NONE;
 80011ba:	2300      	movs	r3, #0
 80011bc:	6603      	str	r3, [r0, #96]	; 0x60
  hspi->State     = HAL_SPI_STATE_READY;
 80011be:	f880 205d 	strb.w	r2, [r0, #93]	; 0x5d

  return HAL_OK;
 80011c2:	4618      	mov	r0, r3
 80011c4:	bd70      	pop	{r4, r5, r6, pc}
  uint32_t frxth;

  /* Check the SPI handle allocation */
  if (hspi == NULL)
  {
    return HAL_ERROR;
 80011c6:	2001      	movs	r0, #1

  hspi->ErrorCode = HAL_SPI_ERROR_NONE;
  hspi->State     = HAL_SPI_STATE_READY;

  return HAL_OK;
}
 80011c8:	bd70      	pop	{r4, r5, r6, pc}

080011ca <HAL_SPI_Transmit>:
  * @param  Size: amount of data to be sent
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
 80011ca:	e92d 41f3 	stmdb	sp!, {r0, r1, r4, r5, r6, r7, r8, lr}
 80011ce:	461e      	mov	r6, r3

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 80011d0:	f890 305c 	ldrb.w	r3, [r0, #92]	; 0x5c
 80011d4:	2b01      	cmp	r3, #1
  * @param  Size: amount of data to be sent
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
 80011d6:	4604      	mov	r4, r0
 80011d8:	460d      	mov	r5, r1
 80011da:	4690      	mov	r8, r2

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 80011dc:	f000 80af 	beq.w	800133e <HAL_SPI_Transmit+0x174>
 80011e0:	2301      	movs	r3, #1
 80011e2:	f880 305c 	strb.w	r3, [r0, #92]	; 0x5c

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();
 80011e6:	f7ff fc27 	bl	8000a38 <HAL_GetTick>
 80011ea:	4607      	mov	r7, r0

  if (hspi->State != HAL_SPI_STATE_READY)
 80011ec:	f894 005d 	ldrb.w	r0, [r4, #93]	; 0x5d
 80011f0:	b2c0      	uxtb	r0, r0
 80011f2:	2801      	cmp	r0, #1
 80011f4:	f040 809b 	bne.w	800132e <HAL_SPI_Transmit+0x164>
  {
    errorcode = HAL_BUSY;
    goto error;
  }

  if ((pData == NULL) || (Size == 0U))
 80011f8:	2d00      	cmp	r5, #0
 80011fa:	f000 8099 	beq.w	8001330 <HAL_SPI_Transmit+0x166>
 80011fe:	f1b8 0f00 	cmp.w	r8, #0
 8001202:	f000 8095 	beq.w	8001330 <HAL_SPI_Transmit+0x166>
    errorcode = HAL_ERROR;
    goto error;
  }

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_TX;
 8001206:	2303      	movs	r3, #3
 8001208:	f884 305d 	strb.w	r3, [r4, #93]	; 0x5d
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
 800120c:	2300      	movs	r3, #0
 800120e:	6623      	str	r3, [r4, #96]	; 0x60
  hspi->pTxBuffPtr  = (uint8_t *)pData;
  hspi->TxXferSize  = Size;
  hspi->TxXferCount = Size;

  /*Init field not used in handle to zero */
  hspi->pRxBuffPtr  = (uint8_t *)NULL;
 8001210:	6423      	str	r3, [r4, #64]	; 0x40
  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_TX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pTxBuffPtr  = (uint8_t *)pData;
  hspi->TxXferSize  = Size;
  hspi->TxXferCount = Size;
 8001212:	f8a4 803e 	strh.w	r8, [r4, #62]	; 0x3e

  /*Init field not used in handle to zero */
  hspi->pRxBuffPtr  = (uint8_t *)NULL;
  hspi->RxXferSize  = 0U;
 8001216:	f8a4 3044 	strh.w	r3, [r4, #68]	; 0x44
  hspi->RxXferCount = 0U;
 800121a:	f8a4 3046 	strh.w	r3, [r4, #70]	; 0x46
  hspi->TxISR       = NULL;
 800121e:	6523      	str	r3, [r4, #80]	; 0x50
  hspi->RxISR       = NULL;
 8001220:	64e3      	str	r3, [r4, #76]	; 0x4c

  /* Configure communication direction : 1Line */
  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
 8001222:	68a3      	ldr	r3, [r4, #8]
 8001224:	6822      	ldr	r2, [r4, #0]
  }

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_TX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pTxBuffPtr  = (uint8_t *)pData;
 8001226:	63a5      	str	r5, [r4, #56]	; 0x38
  hspi->RxXferCount = 0U;
  hspi->TxISR       = NULL;
  hspi->RxISR       = NULL;

  /* Configure communication direction : 1Line */
  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
 8001228:	f5b3 4f00 	cmp.w	r3, #32768	; 0x8000
  {
    SPI_1LINE_TX(hspi);
 800122c:	bf08      	it	eq
 800122e:	6813      	ldreq	r3, [r2, #0]

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_TX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pTxBuffPtr  = (uint8_t *)pData;
  hspi->TxXferSize  = Size;
 8001230:	f8a4 803c 	strh.w	r8, [r4, #60]	; 0x3c
  hspi->RxISR       = NULL;

  /* Configure communication direction : 1Line */
  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
  {
    SPI_1LINE_TX(hspi);
 8001234:	bf04      	itt	eq
 8001236:	f443 4380 	orreq.w	r3, r3, #16384	; 0x4000
 800123a:	6013      	streq	r3, [r2, #0]
    SPI_RESET_CRC(hspi);
  }
#endif /* USE_SPI_CRC */

  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
 800123c:	6813      	ldr	r3, [r2, #0]
 800123e:	065b      	lsls	r3, r3, #25
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
 8001240:	bf5e      	ittt	pl
 8001242:	6813      	ldrpl	r3, [r2, #0]
 8001244:	f043 0340 	orrpl.w	r3, r3, #64	; 0x40
 8001248:	6013      	strpl	r3, [r2, #0]
  }

  /* Transmit data in 16 Bit mode */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 800124a:	68e3      	ldr	r3, [r4, #12]
 800124c:	f5b3 6fe0 	cmp.w	r3, #1792	; 0x700
 8001250:	6863      	ldr	r3, [r4, #4]
 8001252:	d921      	bls.n	8001298 <HAL_SPI_Transmit+0xce>
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
 8001254:	b11b      	cbz	r3, 800125e <HAL_SPI_Transmit+0x94>
 8001256:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001258:	b29b      	uxth	r3, r3
 800125a:	2b01      	cmp	r3, #1
 800125c:	d10a      	bne.n	8001274 <HAL_SPI_Transmit+0xaa>
    {
      hspi->Instance->DR = *((uint16_t *)pData);
 800125e:	f835 3b02 	ldrh.w	r3, [r5], #2
 8001262:	60d3      	str	r3, [r2, #12]
      /* Wait until TXE flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
      {
        hspi->Instance->DR = *((uint16_t *)pData);
        pData += sizeof(uint16_t);
        hspi->TxXferCount--;
 8001264:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001266:	3b01      	subs	r3, #1
 8001268:	b29b      	uxth	r3, r3
 800126a:	87e3      	strh	r3, [r4, #62]	; 0x3e
 800126c:	e002      	b.n	8001274 <HAL_SPI_Transmit+0xaa>
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 800126e:	b18e      	cbz	r6, 8001294 <HAL_SPI_Transmit+0xca>
 8001270:	1c71      	adds	r1, r6, #1
 8001272:	d10a      	bne.n	800128a <HAL_SPI_Transmit+0xc0>
      hspi->Instance->DR = *((uint16_t *)pData);
      pData += sizeof(uint16_t);
      hspi->TxXferCount--;
    }
    /* Transmit data in 16 Bit mode */
    while (hspi->TxXferCount > 0U)
 8001274:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001276:	b29b      	uxth	r3, r3
 8001278:	b1b3      	cbz	r3, 80012a8 <HAL_SPI_Transmit+0xde>
    {
      /* Wait until TXE flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
 800127a:	6823      	ldr	r3, [r4, #0]
 800127c:	689a      	ldr	r2, [r3, #8]
 800127e:	0790      	lsls	r0, r2, #30
 8001280:	d5f5      	bpl.n	800126e <HAL_SPI_Transmit+0xa4>
      {
        hspi->Instance->DR = *((uint16_t *)pData);
 8001282:	f835 2b02 	ldrh.w	r2, [r5], #2
 8001286:	60da      	str	r2, [r3, #12]
 8001288:	e7ec      	b.n	8001264 <HAL_SPI_Transmit+0x9a>
        hspi->TxXferCount--;
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 800128a:	f7ff fbd5 	bl	8000a38 <HAL_GetTick>
 800128e:	1bc0      	subs	r0, r0, r7
 8001290:	4286      	cmp	r6, r0
 8001292:	d8ef      	bhi.n	8001274 <HAL_SPI_Transmit+0xaa>
        {
          errorcode = HAL_TIMEOUT;
 8001294:	2003      	movs	r0, #3
 8001296:	e04b      	b.n	8001330 <HAL_SPI_Transmit+0x166>
    }
  }
  /* Transmit data in 8 Bit mode */
  else
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
 8001298:	b173      	cbz	r3, 80012b8 <HAL_SPI_Transmit+0xee>
 800129a:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 800129c:	b29b      	uxth	r3, r3
 800129e:	2b01      	cmp	r3, #1
 80012a0:	d00a      	beq.n	80012b8 <HAL_SPI_Transmit+0xee>
      {
        *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
        hspi->TxXferCount--;
      }
    }
    while (hspi->TxXferCount > 0U)
 80012a2:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80012a4:	b29b      	uxth	r3, r3
 80012a6:	b993      	cbnz	r3, 80012ce <HAL_SPI_Transmit+0x104>
    SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
  }
#endif /* USE_SPI_CRC */

  /* Check the end of the transaction */
  if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
 80012a8:	4620      	mov	r0, r4
 80012aa:	f7ff ff2f 	bl	800110c <SPI_EndRxTxTransaction.isra.2>
 80012ae:	2800      	cmp	r0, #0
 80012b0:	d02f      	beq.n	8001312 <HAL_SPI_Transmit+0x148>
  {
    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
 80012b2:	2320      	movs	r3, #32
 80012b4:	6623      	str	r3, [r4, #96]	; 0x60
 80012b6:	e02c      	b.n	8001312 <HAL_SPI_Transmit+0x148>
  /* Transmit data in 8 Bit mode */
  else
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
    {
      if (hspi->TxXferCount > 1U)
 80012b8:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80012ba:	b29b      	uxth	r3, r3
 80012bc:	2b01      	cmp	r3, #1
 80012be:	d903      	bls.n	80012c8 <HAL_SPI_Transmit+0xfe>
      {
        /* write on the data register in packing mode */
        hspi->Instance->DR = *((uint16_t *)pData);
 80012c0:	f835 3b02 	ldrh.w	r3, [r5], #2
 80012c4:	60d3      	str	r3, [r2, #12]
 80012c6:	e00d      	b.n	80012e4 <HAL_SPI_Transmit+0x11a>
        pData += sizeof(uint16_t);
        hspi->TxXferCount -= 2U;
      }
      else
      {
        *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
 80012c8:	782b      	ldrb	r3, [r5, #0]
 80012ca:	7313      	strb	r3, [r2, #12]
 80012cc:	e011      	b.n	80012f2 <HAL_SPI_Transmit+0x128>
      }
    }
    while (hspi->TxXferCount > 0U)
    {
      /* Wait until TXE flag is set to send data */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
 80012ce:	6823      	ldr	r3, [r4, #0]
 80012d0:	689a      	ldr	r2, [r3, #8]
 80012d2:	0792      	lsls	r2, r2, #30
 80012d4:	d513      	bpl.n	80012fe <HAL_SPI_Transmit+0x134>
      {
        if (hspi->TxXferCount > 1U)
 80012d6:	8fe2      	ldrh	r2, [r4, #62]	; 0x3e
 80012d8:	b292      	uxth	r2, r2
 80012da:	2a01      	cmp	r2, #1
 80012dc:	d907      	bls.n	80012ee <HAL_SPI_Transmit+0x124>
        {
          /* write on the data register in packing mode */
          hspi->Instance->DR = *((uint16_t *)pData);
 80012de:	f835 2b02 	ldrh.w	r2, [r5], #2
 80012e2:	60da      	str	r2, [r3, #12]
          pData += sizeof(uint16_t);
          hspi->TxXferCount -= 2U;
 80012e4:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80012e6:	3b02      	subs	r3, #2
 80012e8:	b29b      	uxth	r3, r3
 80012ea:	87e3      	strh	r3, [r4, #62]	; 0x3e
 80012ec:	e7d9      	b.n	80012a2 <HAL_SPI_Transmit+0xd8>
        }
        else
        {
          *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
 80012ee:	782a      	ldrb	r2, [r5, #0]
 80012f0:	731a      	strb	r2, [r3, #12]
          hspi->TxXferCount--;
 80012f2:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80012f4:	3b01      	subs	r3, #1
 80012f6:	b29b      	uxth	r3, r3
 80012f8:	87e3      	strh	r3, [r4, #62]	; 0x3e
          pData += sizeof(uint16_t);
          hspi->TxXferCount -= 2U;
        }
        else
        {
          *((__IO uint8_t *)&hspi->Instance->DR) = (*pData++);
 80012fa:	3501      	adds	r5, #1
 80012fc:	e7d1      	b.n	80012a2 <HAL_SPI_Transmit+0xd8>
        }
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 80012fe:	2e00      	cmp	r6, #0
 8001300:	d0c8      	beq.n	8001294 <HAL_SPI_Transmit+0xca>
 8001302:	1c73      	adds	r3, r6, #1
 8001304:	d0cd      	beq.n	80012a2 <HAL_SPI_Transmit+0xd8>
 8001306:	f7ff fb97 	bl	8000a38 <HAL_GetTick>
 800130a:	1bc0      	subs	r0, r0, r7
 800130c:	4286      	cmp	r6, r0
 800130e:	d8c8      	bhi.n	80012a2 <HAL_SPI_Transmit+0xd8>
 8001310:	e7c0      	b.n	8001294 <HAL_SPI_Transmit+0xca>
  {
    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
  }

  /* Clear overrun flag in 2 Lines communication mode because received is not read */
  if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
 8001312:	68a3      	ldr	r3, [r4, #8]
 8001314:	b933      	cbnz	r3, 8001324 <HAL_SPI_Transmit+0x15a>
  {
    __HAL_SPI_CLEAR_OVRFLAG(hspi);
 8001316:	9301      	str	r3, [sp, #4]
 8001318:	6823      	ldr	r3, [r4, #0]
 800131a:	68da      	ldr	r2, [r3, #12]
 800131c:	9201      	str	r2, [sp, #4]
 800131e:	689b      	ldr	r3, [r3, #8]
 8001320:	9301      	str	r3, [sp, #4]
 8001322:	9b01      	ldr	r3, [sp, #4]
  }

  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
 8001324:	6e20      	ldr	r0, [r4, #96]	; 0x60
  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  if (hspi->State != HAL_SPI_STATE_READY)
  {
    errorcode = HAL_BUSY;
 8001326:	3000      	adds	r0, #0
 8001328:	bf18      	it	ne
 800132a:	2001      	movne	r0, #1
 800132c:	e000      	b.n	8001330 <HAL_SPI_Transmit+0x166>
 800132e:	2002      	movs	r0, #2
  {
    errorcode = HAL_ERROR;
  }

error:
  hspi->State = HAL_SPI_STATE_READY;
 8001330:	2301      	movs	r3, #1
 8001332:	f884 305d 	strb.w	r3, [r4, #93]	; 0x5d
  /* Process Unlocked */
  __HAL_UNLOCK(hspi);
 8001336:	2300      	movs	r3, #0
 8001338:	f884 305c 	strb.w	r3, [r4, #92]	; 0x5c
  return errorcode;
 800133c:	e000      	b.n	8001340 <HAL_SPI_Transmit+0x176>

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 800133e:	2002      	movs	r0, #2
error:
  hspi->State = HAL_SPI_STATE_READY;
  /* Process Unlocked */
  __HAL_UNLOCK(hspi);
  return errorcode;
}
 8001340:	b002      	add	sp, #8
 8001342:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

08001346 <HAL_SPI_TransmitReceive>:
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
                                          uint32_t Timeout)
{
 8001346:	e92d 43f8 	stmdb	sp!, {r3, r4, r5, r6, r7, r8, r9, lr}
 800134a:	461f      	mov	r7, r3

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 800134c:	f890 305c 	ldrb.w	r3, [r0, #92]	; 0x5c
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
                                          uint32_t Timeout)
{
 8001350:	f8dd 8020 	ldr.w	r8, [sp, #32]

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 8001354:	2b01      	cmp	r3, #1
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,
                                          uint32_t Timeout)
{
 8001356:	4604      	mov	r4, r0
 8001358:	460d      	mov	r5, r1
 800135a:	4616      	mov	r6, r2

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 800135c:	f000 8120 	beq.w	80015a0 <HAL_SPI_TransmitReceive+0x25a>
 8001360:	2301      	movs	r3, #1
 8001362:	f880 305c 	strb.w	r3, [r0, #92]	; 0x5c

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();
 8001366:	f7ff fb67 	bl	8000a38 <HAL_GetTick>

  tmp  = hspi->State;
 800136a:	f894 305d 	ldrb.w	r3, [r4, #93]	; 0x5d
  tmp1 = hspi->Init.Mode;
 800136e:	6861      	ldr	r1, [r4, #4]
  __HAL_LOCK(hspi);

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  tmp  = hspi->State;
 8001370:	b2db      	uxtb	r3, r3
  tmp1 = hspi->Init.Mode;

  if (!((tmp == HAL_SPI_STATE_READY) || \
 8001372:	2b01      	cmp	r3, #1

  /* Process Locked */
  __HAL_LOCK(hspi);

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();
 8001374:	4681      	mov	r9, r0

  tmp  = hspi->State;
  tmp1 = hspi->Init.Mode;

  if (!((tmp == HAL_SPI_STATE_READY) || \
 8001376:	d00a      	beq.n	800138e <HAL_SPI_TransmitReceive+0x48>
 8001378:	f5b1 7f82 	cmp.w	r1, #260	; 0x104
 800137c:	f040 8105 	bne.w	800158a <HAL_SPI_TransmitReceive+0x244>
        ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX))))
 8001380:	68a2      	ldr	r2, [r4, #8]
 8001382:	2a00      	cmp	r2, #0
 8001384:	f040 8101 	bne.w	800158a <HAL_SPI_TransmitReceive+0x244>
 8001388:	2b04      	cmp	r3, #4
 800138a:	f040 80fe 	bne.w	800158a <HAL_SPI_TransmitReceive+0x244>
  {
    errorcode = HAL_BUSY;
    goto error;
  }

  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
 800138e:	2d00      	cmp	r5, #0
 8001390:	f000 80fd 	beq.w	800158e <HAL_SPI_TransmitReceive+0x248>
 8001394:	2e00      	cmp	r6, #0
 8001396:	f000 80fa 	beq.w	800158e <HAL_SPI_TransmitReceive+0x248>
 800139a:	2f00      	cmp	r7, #0
 800139c:	f000 80f7 	beq.w	800158e <HAL_SPI_TransmitReceive+0x248>
    errorcode = HAL_ERROR;
    goto error;
  }

  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
 80013a0:	f894 305d 	ldrb.w	r3, [r4, #93]	; 0x5d
    SPI_RESET_CRC(hspi);
  }
#endif /* USE_SPI_CRC */

  /* Set the Rx Fifo threshold */
  if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U))
 80013a4:	68e0      	ldr	r0, [r4, #12]
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
 80013a6:	6426      	str	r6, [r4, #64]	; 0x40
    errorcode = HAL_ERROR;
    goto error;
  }

  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
 80013a8:	2b04      	cmp	r3, #4
  {
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
 80013aa:	bf1c      	itt	ne
 80013ac:	2305      	movne	r3, #5
 80013ae:	f884 305d 	strbne.w	r3, [r4, #93]	; 0x5d
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
 80013b2:	2300      	movs	r3, #0
    SPI_RESET_CRC(hspi);
  }
#endif /* USE_SPI_CRC */

  /* Set the Rx Fifo threshold */
  if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U))
 80013b4:	f5b0 6fe0 	cmp.w	r0, #1792	; 0x700
  {
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
 80013b8:	6623      	str	r3, [r4, #96]	; 0x60
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
  hspi->TxXferCount = Size;
  hspi->TxXferSize  = Size;

  /*Init field not used in handle to zero */
  hspi->RxISR       = NULL;
 80013ba:	64e3      	str	r3, [r4, #76]	; 0x4c
  }

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
  hspi->RxXferCount = Size;
 80013bc:	f8a4 7046 	strh.w	r7, [r4, #70]	; 0x46
  hspi->TxXferCount = Size;
  hspi->TxXferSize  = Size;

  /*Init field not used in handle to zero */
  hspi->RxISR       = NULL;
  hspi->TxISR       = NULL;
 80013c0:	6523      	str	r3, [r4, #80]	; 0x50

  /* Set the transaction information */
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
  hspi->RxXferCount = Size;
  hspi->RxXferSize  = Size;
 80013c2:	f8a4 7044 	strh.w	r7, [r4, #68]	; 0x44
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
 80013c6:	63a5      	str	r5, [r4, #56]	; 0x38
  hspi->TxXferCount = Size;
 80013c8:	87e7      	strh	r7, [r4, #62]	; 0x3e
  hspi->TxXferSize  = Size;
 80013ca:	87a7      	strh	r7, [r4, #60]	; 0x3c
 80013cc:	6823      	ldr	r3, [r4, #0]
    SPI_RESET_CRC(hspi);
  }
#endif /* USE_SPI_CRC */

  /* Set the Rx Fifo threshold */
  if ((hspi->Init.DataSize > SPI_DATASIZE_8BIT) || (hspi->RxXferCount > 1U))
 80013ce:	d804      	bhi.n	80013da <HAL_SPI_TransmitReceive+0x94>
 80013d0:	f8b4 2046 	ldrh.w	r2, [r4, #70]	; 0x46
 80013d4:	b292      	uxth	r2, r2
 80013d6:	2a01      	cmp	r2, #1
 80013d8:	d903      	bls.n	80013e2 <HAL_SPI_TransmitReceive+0x9c>
  {
    /* set fiforxthreshold according the reception data length: 16bit */
    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 80013da:	685a      	ldr	r2, [r3, #4]
 80013dc:	f422 5280 	bic.w	r2, r2, #4096	; 0x1000
 80013e0:	e002      	b.n	80013e8 <HAL_SPI_TransmitReceive+0xa2>
  }
  else
  {
    /* set fiforxthreshold according the reception data length: 8bit */
    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 80013e2:	685a      	ldr	r2, [r3, #4]
 80013e4:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
 80013e8:	605a      	str	r2, [r3, #4]
  }

  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
 80013ea:	681a      	ldr	r2, [r3, #0]
 80013ec:	0652      	lsls	r2, r2, #25
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
 80013ee:	bf5e      	ittt	pl
 80013f0:	681a      	ldrpl	r2, [r3, #0]
 80013f2:	f042 0240 	orrpl.w	r2, r2, #64	; 0x40
 80013f6:	601a      	strpl	r2, [r3, #0]
  }

  /* Transmit and Receive data in 16 Bit mode */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 80013f8:	f5b0 6fe0 	cmp.w	r0, #1792	; 0x700
 80013fc:	d94b      	bls.n	8001496 <HAL_SPI_TransmitReceive+0x150>
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
 80013fe:	b119      	cbz	r1, 8001408 <HAL_SPI_TransmitReceive+0xc2>
 8001400:	8fe2      	ldrh	r2, [r4, #62]	; 0x3e
 8001402:	b292      	uxth	r2, r2
 8001404:	2a01      	cmp	r2, #1
 8001406:	d106      	bne.n	8001416 <HAL_SPI_TransmitReceive+0xd0>
    {
      hspi->Instance->DR = *((uint16_t *)pTxData);
 8001408:	f835 2b02 	ldrh.w	r2, [r5], #2
 800140c:	60da      	str	r2, [r3, #12]
      pTxData += sizeof(uint16_t);
      hspi->TxXferCount--;
 800140e:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001410:	3b01      	subs	r3, #1
 8001412:	b29b      	uxth	r3, r3
 8001414:	87e3      	strh	r3, [r4, #62]	; 0x3e
      {
        *((uint16_t *)pRxData) = hspi->Instance->DR;
        pRxData += sizeof(uint16_t);
        hspi->RxXferCount--;
        /* Next Data is a Transmission (Tx). Tx is allowed */
        txallowed = 1U;
 8001416:	2701      	movs	r7, #1
    {
      hspi->Instance->DR = *((uint16_t *)pTxData);
      pTxData += sizeof(uint16_t);
      hspi->TxXferCount--;
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
 8001418:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 800141a:	b29b      	uxth	r3, r3
 800141c:	b373      	cbz	r3, 800147c <HAL_SPI_TransmitReceive+0x136>
    {
      /* Check TXE flag */
      if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
 800141e:	b187      	cbz	r7, 8001442 <HAL_SPI_TransmitReceive+0xfc>
 8001420:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001422:	b29b      	uxth	r3, r3
 8001424:	b163      	cbz	r3, 8001440 <HAL_SPI_TransmitReceive+0xfa>
 8001426:	6823      	ldr	r3, [r4, #0]
 8001428:	689a      	ldr	r2, [r3, #8]
 800142a:	0797      	lsls	r7, r2, #30
 800142c:	d508      	bpl.n	8001440 <HAL_SPI_TransmitReceive+0xfa>
      {
        hspi->Instance->DR = *((uint16_t *)pTxData);
 800142e:	f835 2b02 	ldrh.w	r2, [r5], #2
 8001432:	60da      	str	r2, [r3, #12]
        pTxData += sizeof(uint16_t);
        hspi->TxXferCount--;
 8001434:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 8001436:	3b01      	subs	r3, #1
 8001438:	b29b      	uxth	r3, r3
 800143a:	87e3      	strh	r3, [r4, #62]	; 0x3e
        /* Next Data is a reception (Rx). Tx not allowed */
        txallowed = 0U;
 800143c:	2700      	movs	r7, #0
 800143e:	e000      	b.n	8001442 <HAL_SPI_TransmitReceive+0xfc>
      hspi->TxXferCount--;
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* Check TXE flag */
      if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
 8001440:	2701      	movs	r7, #1
        }
#endif /* USE_SPI_CRC */
      }

      /* Check RXNE flag */
      if ((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)))
 8001442:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001446:	b29b      	uxth	r3, r3
 8001448:	b16b      	cbz	r3, 8001466 <HAL_SPI_TransmitReceive+0x120>
 800144a:	6823      	ldr	r3, [r4, #0]
 800144c:	689a      	ldr	r2, [r3, #8]
 800144e:	07d0      	lsls	r0, r2, #31
 8001450:	d509      	bpl.n	8001466 <HAL_SPI_TransmitReceive+0x120>
      {
        *((uint16_t *)pRxData) = hspi->Instance->DR;
 8001452:	68db      	ldr	r3, [r3, #12]
 8001454:	f826 3b02 	strh.w	r3, [r6], #2
        pRxData += sizeof(uint16_t);
        hspi->RxXferCount--;
 8001458:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 800145c:	3b01      	subs	r3, #1
 800145e:	b29b      	uxth	r3, r3
 8001460:	f8a4 3046 	strh.w	r3, [r4, #70]	; 0x46
        /* Next Data is a Transmission (Tx). Tx is allowed */
        txallowed = 1U;
 8001464:	2701      	movs	r7, #1
      }
      if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout))
 8001466:	f1b8 3fff 	cmp.w	r8, #4294967295	; 0xffffffff
 800146a:	d0d5      	beq.n	8001418 <HAL_SPI_TransmitReceive+0xd2>
 800146c:	f7ff fae4 	bl	8000a38 <HAL_GetTick>
 8001470:	ebc9 0000 	rsb	r0, r9, r0
 8001474:	4580      	cmp	r8, r0
 8001476:	d8cf      	bhi.n	8001418 <HAL_SPI_TransmitReceive+0xd2>
      {
        errorcode = HAL_TIMEOUT;
 8001478:	2003      	movs	r0, #3
 800147a:	e089      	b.n	8001590 <HAL_SPI_TransmitReceive+0x24a>
    {
      hspi->Instance->DR = *((uint16_t *)pTxData);
      pTxData += sizeof(uint16_t);
      hspi->TxXferCount--;
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
 800147c:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001480:	b29b      	uxth	r3, r3
 8001482:	2b00      	cmp	r3, #0
 8001484:	d1cb      	bne.n	800141e <HAL_SPI_TransmitReceive+0xd8>
    errorcode = HAL_ERROR;
  }
#endif /* USE_SPI_CRC */

  /* Check the end of the transaction */
  if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
 8001486:	4620      	mov	r0, r4
 8001488:	f7ff fe40 	bl	800110c <SPI_EndRxTxTransaction.isra.2>
 800148c:	2800      	cmp	r0, #0
 800148e:	d077      	beq.n	8001580 <HAL_SPI_TransmitReceive+0x23a>
  {
    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
 8001490:	2320      	movs	r3, #32
 8001492:	6623      	str	r3, [r4, #96]	; 0x60
 8001494:	e074      	b.n	8001580 <HAL_SPI_TransmitReceive+0x23a>
    }
  }
  /* Transmit and Receive data in 8 Bit mode */
  else
  {
    if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (hspi->TxXferCount == 0x01U))
 8001496:	b119      	cbz	r1, 80014a0 <HAL_SPI_TransmitReceive+0x15a>
 8001498:	8fe2      	ldrh	r2, [r4, #62]	; 0x3e
 800149a:	b292      	uxth	r2, r2
 800149c:	2a01      	cmp	r2, #1
 800149e:	d112      	bne.n	80014c6 <HAL_SPI_TransmitReceive+0x180>
    {
      if (hspi->TxXferCount > 1U)
 80014a0:	8fe2      	ldrh	r2, [r4, #62]	; 0x3e
 80014a2:	b292      	uxth	r2, r2
 80014a4:	2a01      	cmp	r2, #1
 80014a6:	d907      	bls.n	80014b8 <HAL_SPI_TransmitReceive+0x172>
      {
        hspi->Instance->DR = *((uint16_t *)pTxData);
 80014a8:	f835 2b02 	ldrh.w	r2, [r5], #2
 80014ac:	60da      	str	r2, [r3, #12]
        pTxData += sizeof(uint16_t);
        hspi->TxXferCount -= 2U;
 80014ae:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014b0:	3b02      	subs	r3, #2
 80014b2:	b29b      	uxth	r3, r3
 80014b4:	87e3      	strh	r3, [r4, #62]	; 0x3e
 80014b6:	e006      	b.n	80014c6 <HAL_SPI_TransmitReceive+0x180>
      }
      else
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
 80014b8:	782a      	ldrb	r2, [r5, #0]
 80014ba:	731a      	strb	r2, [r3, #12]
        hspi->TxXferCount--;
 80014bc:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014be:	3b01      	subs	r3, #1
 80014c0:	b29b      	uxth	r3, r3
 80014c2:	87e3      	strh	r3, [r4, #62]	; 0x3e
        pTxData += sizeof(uint16_t);
        hspi->TxXferCount -= 2U;
      }
      else
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
 80014c4:	3501      	adds	r5, #1
        {
          (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR;
          hspi->RxXferCount--;
        }
        /* Next Data is a Transmission (Tx). Tx is allowed */
        txallowed = 1U;
 80014c6:	2701      	movs	r7, #1
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
        hspi->TxXferCount--;
      }
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
 80014c8:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014ca:	b29b      	uxth	r3, r3
 80014cc:	2b00      	cmp	r3, #0
 80014ce:	d051      	beq.n	8001574 <HAL_SPI_TransmitReceive+0x22e>
    {
      /* check TXE flag */
      if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
 80014d0:	b1e7      	cbz	r7, 800150c <HAL_SPI_TransmitReceive+0x1c6>
 80014d2:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014d4:	b29b      	uxth	r3, r3
 80014d6:	b1c3      	cbz	r3, 800150a <HAL_SPI_TransmitReceive+0x1c4>
 80014d8:	6823      	ldr	r3, [r4, #0]
 80014da:	689a      	ldr	r2, [r3, #8]
 80014dc:	0791      	lsls	r1, r2, #30
 80014de:	d514      	bpl.n	800150a <HAL_SPI_TransmitReceive+0x1c4>
      {
        if (hspi->TxXferCount > 1U)
 80014e0:	8fe2      	ldrh	r2, [r4, #62]	; 0x3e
 80014e2:	b292      	uxth	r2, r2
 80014e4:	2a01      	cmp	r2, #1
 80014e6:	d907      	bls.n	80014f8 <HAL_SPI_TransmitReceive+0x1b2>
        {
          hspi->Instance->DR = *((uint16_t *)pTxData);
 80014e8:	f835 2b02 	ldrh.w	r2, [r5], #2
 80014ec:	60da      	str	r2, [r3, #12]
          pTxData += sizeof(uint16_t);
          hspi->TxXferCount -= 2U;
 80014ee:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014f0:	3b02      	subs	r3, #2
 80014f2:	b29b      	uxth	r3, r3
 80014f4:	87e3      	strh	r3, [r4, #62]	; 0x3e
 80014f6:	e006      	b.n	8001506 <HAL_SPI_TransmitReceive+0x1c0>
        }
        else
        {
          *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
 80014f8:	782a      	ldrb	r2, [r5, #0]
 80014fa:	731a      	strb	r2, [r3, #12]
          hspi->TxXferCount--;
 80014fc:	8fe3      	ldrh	r3, [r4, #62]	; 0x3e
 80014fe:	3b01      	subs	r3, #1
 8001500:	b29b      	uxth	r3, r3
 8001502:	87e3      	strh	r3, [r4, #62]	; 0x3e
          pTxData += sizeof(uint16_t);
          hspi->TxXferCount -= 2U;
        }
        else
        {
          *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
 8001504:	3501      	adds	r5, #1
          hspi->TxXferCount--;
        }
        /* Next Data is a reception (Rx). Tx not allowed */
        txallowed = 0U;
 8001506:	2700      	movs	r7, #0
 8001508:	e000      	b.n	800150c <HAL_SPI_TransmitReceive+0x1c6>
      }
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
    {
      /* check TXE flag */
      if (txallowed && (hspi->TxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)))
 800150a:	2701      	movs	r7, #1
        }
#endif /* USE_SPI_CRC */
      }

      /* Wait until RXNE flag is reset */
      if ((hspi->RxXferCount > 0U) && (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)))
 800150c:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001510:	b29b      	uxth	r3, r3
 8001512:	b32b      	cbz	r3, 8001560 <HAL_SPI_TransmitReceive+0x21a>
 8001514:	6823      	ldr	r3, [r4, #0]
 8001516:	689a      	ldr	r2, [r3, #8]
 8001518:	07d2      	lsls	r2, r2, #31
 800151a:	d521      	bpl.n	8001560 <HAL_SPI_TransmitReceive+0x21a>
      {
        if (hspi->RxXferCount > 1U)
 800151c:	f8b4 2046 	ldrh.w	r2, [r4, #70]	; 0x46
 8001520:	b292      	uxth	r2, r2
 8001522:	2a01      	cmp	r2, #1
 8001524:	d912      	bls.n	800154c <HAL_SPI_TransmitReceive+0x206>
        {
          *((uint16_t *)pRxData) = hspi->Instance->DR;
 8001526:	68da      	ldr	r2, [r3, #12]
 8001528:	f826 2b02 	strh.w	r2, [r6], #2
          pRxData += sizeof(uint16_t);
          hspi->RxXferCount -= 2U;
 800152c:	f8b4 2046 	ldrh.w	r2, [r4, #70]	; 0x46
 8001530:	3a02      	subs	r2, #2
 8001532:	b292      	uxth	r2, r2
 8001534:	f8a4 2046 	strh.w	r2, [r4, #70]	; 0x46
          if (hspi->RxXferCount <= 1U)
 8001538:	f8b4 2046 	ldrh.w	r2, [r4, #70]	; 0x46
 800153c:	b292      	uxth	r2, r2
 800153e:	2a01      	cmp	r2, #1
 8001540:	d80d      	bhi.n	800155e <HAL_SPI_TransmitReceive+0x218>
          {
            /* set fiforxthresold before to switch on 8 bit data size */
            SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 8001542:	685a      	ldr	r2, [r3, #4]
 8001544:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
 8001548:	605a      	str	r2, [r3, #4]
 800154a:	e008      	b.n	800155e <HAL_SPI_TransmitReceive+0x218>
          }
        }
        else
        {
          (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR;
 800154c:	7b1b      	ldrb	r3, [r3, #12]
 800154e:	7033      	strb	r3, [r6, #0]
          hspi->RxXferCount--;
 8001550:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001554:	3b01      	subs	r3, #1
 8001556:	b29b      	uxth	r3, r3
 8001558:	f8a4 3046 	strh.w	r3, [r4, #70]	; 0x46
            SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
          }
        }
        else
        {
          (*(uint8_t *)pRxData++) = *(__IO uint8_t *)&hspi->Instance->DR;
 800155c:	3601      	adds	r6, #1
          hspi->RxXferCount--;
        }
        /* Next Data is a Transmission (Tx). Tx is allowed */
        txallowed = 1U;
 800155e:	2701      	movs	r7, #1
      }
      if ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout))
 8001560:	f1b8 3fff 	cmp.w	r8, #4294967295	; 0xffffffff
 8001564:	d0b0      	beq.n	80014c8 <HAL_SPI_TransmitReceive+0x182>
 8001566:	f7ff fa67 	bl	8000a38 <HAL_GetTick>
 800156a:	ebc9 0000 	rsb	r0, r9, r0
 800156e:	4580      	cmp	r8, r0
 8001570:	d8aa      	bhi.n	80014c8 <HAL_SPI_TransmitReceive+0x182>
 8001572:	e781      	b.n	8001478 <HAL_SPI_TransmitReceive+0x132>
      {
        *(__IO uint8_t *)&hspi->Instance->DR = (*pTxData++);
        hspi->TxXferCount--;
      }
    }
    while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
 8001574:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001578:	b29b      	uxth	r3, r3
 800157a:	2b00      	cmp	r3, #0
 800157c:	d1a8      	bne.n	80014d0 <HAL_SPI_TransmitReceive+0x18a>
 800157e:	e782      	b.n	8001486 <HAL_SPI_TransmitReceive+0x140>
  if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
  {
    hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
  }

  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
 8001580:	6e20      	ldr	r0, [r4, #96]	; 0x60
  tmp1 = hspi->Init.Mode;

  if (!((tmp == HAL_SPI_STATE_READY) || \
        ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX))))
  {
    errorcode = HAL_BUSY;
 8001582:	3000      	adds	r0, #0
 8001584:	bf18      	it	ne
 8001586:	2001      	movne	r0, #1
 8001588:	e002      	b.n	8001590 <HAL_SPI_TransmitReceive+0x24a>
 800158a:	2002      	movs	r0, #2
 800158c:	e000      	b.n	8001590 <HAL_SPI_TransmitReceive+0x24a>
    goto error;
  }

  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
  {
    errorcode = HAL_ERROR;
 800158e:	2001      	movs	r0, #1
  {
    errorcode = HAL_ERROR;
  }

error :
  hspi->State = HAL_SPI_STATE_READY;
 8001590:	2301      	movs	r3, #1
 8001592:	f884 305d 	strb.w	r3, [r4, #93]	; 0x5d
  __HAL_UNLOCK(hspi);
 8001596:	2300      	movs	r3, #0
 8001598:	f884 305c 	strb.w	r3, [r4, #92]	; 0x5c
 800159c:	e8bd 83f8 	ldmia.w	sp!, {r3, r4, r5, r6, r7, r8, r9, pc}

  /* Check Direction parameter */
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));

  /* Process Locked */
  __HAL_LOCK(hspi);
 80015a0:	2002      	movs	r0, #2

error :
  hspi->State = HAL_SPI_STATE_READY;
  __HAL_UNLOCK(hspi);
  return errorcode;
}
 80015a2:	e8bd 83f8 	ldmia.w	sp!, {r3, r4, r5, r6, r7, r8, r9, pc}

080015a6 <HAL_SPI_Receive>:
  * @param  Size: amount of data to be received
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
 80015a6:	e92d 41ff 	stmdb	sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr}
 80015aa:	461e      	mov	r6, r3
#endif /* USE_SPI_CRC */
  uint32_t tickstart = 0U;
  HAL_StatusTypeDef errorcode = HAL_OK;


  if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
 80015ac:	6843      	ldr	r3, [r0, #4]
 80015ae:	f5b3 7f82 	cmp.w	r3, #260	; 0x104
  * @param  Size: amount of data to be received
  * @param  Timeout: Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
 80015b2:	4604      	mov	r4, r0
 80015b4:	460d      	mov	r5, r1
 80015b6:	4690      	mov	r8, r2
#endif /* USE_SPI_CRC */
  uint32_t tickstart = 0U;
  HAL_StatusTypeDef errorcode = HAL_OK;


  if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
 80015b8:	d10a      	bne.n	80015d0 <HAL_SPI_Receive+0x2a>
 80015ba:	6883      	ldr	r3, [r0, #8]
 80015bc:	b943      	cbnz	r3, 80015d0 <HAL_SPI_Receive+0x2a>
  {
    hspi->State = HAL_SPI_STATE_BUSY_RX;
 80015be:	2304      	movs	r3, #4
 80015c0:	f880 305d 	strb.w	r3, [r0, #93]	; 0x5d
    /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
    return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
 80015c4:	4613      	mov	r3, r2
 80015c6:	9600      	str	r6, [sp, #0]
 80015c8:	460a      	mov	r2, r1
 80015ca:	f7ff febc 	bl	8001346 <HAL_SPI_TransmitReceive>
 80015ce:	e0b3      	b.n	8001738 <HAL_SPI_Receive+0x192>
  }

  /* Process Locked */
  __HAL_LOCK(hspi);
 80015d0:	f894 305c 	ldrb.w	r3, [r4, #92]	; 0x5c
 80015d4:	2b01      	cmp	r3, #1
 80015d6:	f000 8093 	beq.w	8001700 <HAL_SPI_Receive+0x15a>
 80015da:	2301      	movs	r3, #1
 80015dc:	f884 305c 	strb.w	r3, [r4, #92]	; 0x5c

  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();
 80015e0:	f7ff fa2a 	bl	8000a38 <HAL_GetTick>
 80015e4:	4607      	mov	r7, r0

  if (hspi->State != HAL_SPI_STATE_READY)
 80015e6:	f894 005d 	ldrb.w	r0, [r4, #93]	; 0x5d
 80015ea:	b2c0      	uxtb	r0, r0
 80015ec:	2801      	cmp	r0, #1
 80015ee:	d17f      	bne.n	80016f0 <HAL_SPI_Receive+0x14a>
  {
    errorcode = HAL_BUSY;
    goto error;
  }

  if ((pData == NULL) || (Size == 0U))
 80015f0:	2d00      	cmp	r5, #0
 80015f2:	d07e      	beq.n	80016f2 <HAL_SPI_Receive+0x14c>
 80015f4:	f1b8 0f00 	cmp.w	r8, #0
 80015f8:	d07b      	beq.n	80016f2 <HAL_SPI_Receive+0x14c>
    errorcode = HAL_ERROR;
    goto error;
  }

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_RX;
 80015fa:	2304      	movs	r3, #4
 80015fc:	f884 305d 	strb.w	r3, [r4, #93]	; 0x5d
 8001600:	6822      	ldr	r2, [r4, #0]
    hspi->RxXferCount--;
  }
#endif /* USE_SPI_CRC */

  /* Set the Rx Fifo threshold */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 8001602:	68e1      	ldr	r1, [r4, #12]
  }

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_RX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pData;
 8001604:	6425      	str	r5, [r4, #64]	; 0x40
    goto error;
  }

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_RX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
 8001606:	2300      	movs	r3, #0
 8001608:	6623      	str	r3, [r4, #96]	; 0x60
  hspi->pRxBuffPtr  = (uint8_t *)pData;
  hspi->RxXferSize  = Size;
  hspi->RxXferCount = Size;
 800160a:	f8a4 8046 	strh.w	r8, [r4, #70]	; 0x46

  /*Init field not used in handle to zero */
  hspi->pTxBuffPtr  = (uint8_t *)NULL;
  hspi->TxXferSize  = 0U;
  hspi->TxXferCount = 0U;
 800160e:	87e3      	strh	r3, [r4, #62]	; 0x3e
  hspi->pRxBuffPtr  = (uint8_t *)pData;
  hspi->RxXferSize  = Size;
  hspi->RxXferCount = Size;

  /*Init field not used in handle to zero */
  hspi->pTxBuffPtr  = (uint8_t *)NULL;
 8001610:	63a3      	str	r3, [r4, #56]	; 0x38
  hspi->TxXferSize  = 0U;
 8001612:	87a3      	strh	r3, [r4, #60]	; 0x3c
  hspi->TxXferCount = 0U;
  hspi->RxISR       = NULL;
 8001614:	64e3      	str	r3, [r4, #76]	; 0x4c
  hspi->TxISR       = NULL;
 8001616:	6523      	str	r3, [r4, #80]	; 0x50

  /* Set the Rx Fifo threshold */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
  {
    /* set fiforxthresold according the reception data length: 16bit */
    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 8001618:	6853      	ldr	r3, [r2, #4]

  /* Set the transaction information */
  hspi->State       = HAL_SPI_STATE_BUSY_RX;
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  hspi->pRxBuffPtr  = (uint8_t *)pData;
  hspi->RxXferSize  = Size;
 800161a:	f8a4 8044 	strh.w	r8, [r4, #68]	; 0x44
    hspi->RxXferCount--;
  }
#endif /* USE_SPI_CRC */

  /* Set the Rx Fifo threshold */
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
 800161e:	f5b1 6fe0 	cmp.w	r1, #1792	; 0x700
  {
    /* set fiforxthresold according the reception data length: 16bit */
    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 8001622:	bf8c      	ite	hi
 8001624:	f423 5380 	bichi.w	r3, r3, #4096	; 0x1000
  }
  else
  {
    /* set fiforxthresold according the reception data length: 8bit */
    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
 8001628:	f443 5380 	orrls.w	r3, r3, #4096	; 0x1000
 800162c:	6053      	str	r3, [r2, #4]
  }

  /* Configure communication direction: 1Line */
  if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
 800162e:	68a3      	ldr	r3, [r4, #8]
 8001630:	f5b3 4f00 	cmp.w	r3, #32768	; 0x8000
  {
    SPI_1LINE_RX(hspi);
 8001634:	bf02      	ittt	eq
 8001636:	6813      	ldreq	r3, [r2, #0]
 8001638:	f423 4380 	biceq.w	r3, r3, #16384	; 0x4000
 800163c:	6013      	streq	r3, [r2, #0]
  }

  /* Check if the SPI is already enabled */
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
 800163e:	6813      	ldr	r3, [r2, #0]
 8001640:	065b      	lsls	r3, r3, #25
  {
    /* Enable SPI peripheral */
    __HAL_SPI_ENABLE(hspi);
 8001642:	bf5e      	ittt	pl
 8001644:	6813      	ldrpl	r3, [r2, #0]
 8001646:	f043 0340 	orrpl.w	r3, r3, #64	; 0x40
 800164a:	6013      	strpl	r3, [r2, #0]
  }

  /* Receive data in 8 Bit mode */
  if (hspi->Init.DataSize <= SPI_DATASIZE_8BIT)
 800164c:	f5b1 6fe0 	cmp.w	r1, #1792	; 0x700
 8001650:	d829      	bhi.n	80016a6 <HAL_SPI_Receive+0x100>
  {
    /* Transfer loop */
    while (hspi->RxXferCount > 0U)
 8001652:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 8001656:	b29b      	uxth	r3, r3
 8001658:	b353      	cbz	r3, 80016b0 <HAL_SPI_Receive+0x10a>
    {
      /* Check the RXNE flag */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
 800165a:	6823      	ldr	r3, [r4, #0]
 800165c:	689a      	ldr	r2, [r3, #8]
 800165e:	07d0      	lsls	r0, r2, #31
 8001660:	d509      	bpl.n	8001676 <HAL_SPI_Receive+0xd0>
      {
        /* read the received data */
        (* (uint8_t *)pData) = *(__IO uint8_t *)&hspi->Instance->DR;
 8001662:	7b1b      	ldrb	r3, [r3, #12]
 8001664:	f805 3b01 	strb.w	r3, [r5], #1
        pData += sizeof(uint8_t);
        hspi->RxXferCount--;
 8001668:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 800166c:	3b01      	subs	r3, #1
 800166e:	b29b      	uxth	r3, r3
 8001670:	f8a4 3046 	strh.w	r3, [r4, #70]	; 0x46
 8001674:	e7ed      	b.n	8001652 <HAL_SPI_Receive+0xac>
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 8001676:	b90e      	cbnz	r6, 800167c <HAL_SPI_Receive+0xd6>
        {
          errorcode = HAL_TIMEOUT;
 8001678:	2003      	movs	r0, #3
 800167a:	e03a      	b.n	80016f2 <HAL_SPI_Receive+0x14c>
        hspi->RxXferCount--;
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 800167c:	1c71      	adds	r1, r6, #1
 800167e:	d0e8      	beq.n	8001652 <HAL_SPI_Receive+0xac>
 8001680:	f7ff f9da 	bl	8000a38 <HAL_GetTick>
 8001684:	1bc0      	subs	r0, r0, r7
 8001686:	4286      	cmp	r6, r0
 8001688:	d8e3      	bhi.n	8001652 <HAL_SPI_Receive+0xac>
 800168a:	e7f5      	b.n	8001678 <HAL_SPI_Receive+0xd2>
  {
    /* Transfer loop */
    while (hspi->RxXferCount > 0U)
    {
      /* Check the RXNE flag */
      if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
 800168c:	6823      	ldr	r3, [r4, #0]
 800168e:	689a      	ldr	r2, [r3, #8]
 8001690:	07d2      	lsls	r2, r2, #31
 8001692:	d513      	bpl.n	80016bc <HAL_SPI_Receive+0x116>
      {
        *((uint16_t *)pData) = hspi->Instance->DR;
 8001694:	68db      	ldr	r3, [r3, #12]
 8001696:	f825 3b02 	strh.w	r3, [r5], #2
        pData += sizeof(uint16_t);
        hspi->RxXferCount--;
 800169a:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 800169e:	3b01      	subs	r3, #1
 80016a0:	b29b      	uxth	r3, r3
 80016a2:	f8a4 3046 	strh.w	r3, [r4, #70]	; 0x46
    }
  }
  else
  {
    /* Transfer loop */
    while (hspi->RxXferCount > 0U)
 80016a6:	f8b4 3046 	ldrh.w	r3, [r4, #70]	; 0x46
 80016aa:	b29b      	uxth	r3, r3
 80016ac:	2b00      	cmp	r3, #0
 80016ae:	d1ed      	bne.n	800168c <HAL_SPI_Receive+0xe6>
  * @param  Tickstart: tick start value
  * @retval HAL status
  */
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi,  uint32_t Timeout, uint32_t Tickstart)
{
  if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
 80016b0:	6861      	ldr	r1, [r4, #4]
 80016b2:	6823      	ldr	r3, [r4, #0]
 80016b4:	f5b1 7f82 	cmp.w	r1, #260	; 0x104
 80016b8:	d115      	bne.n	80016e6 <HAL_SPI_Receive+0x140>
 80016ba:	e009      	b.n	80016d0 <HAL_SPI_Receive+0x12a>
        hspi->RxXferCount--;
      }
      else
      {
        /* Timeout management */
        if ((Timeout == 0U) || ((Timeout != HAL_MAX_DELAY) && ((HAL_GetTick() - tickstart) >=  Timeout)))
 80016bc:	2e00      	cmp	r6, #0
 80016be:	d0db      	beq.n	8001678 <HAL_SPI_Receive+0xd2>
 80016c0:	1c73      	adds	r3, r6, #1
 80016c2:	d0f0      	beq.n	80016a6 <HAL_SPI_Receive+0x100>
 80016c4:	f7ff f9b8 	bl	8000a38 <HAL_GetTick>
 80016c8:	1bc0      	subs	r0, r0, r7
 80016ca:	4286      	cmp	r6, r0
 80016cc:	d8eb      	bhi.n	80016a6 <HAL_SPI_Receive+0x100>
 80016ce:	e7d3      	b.n	8001678 <HAL_SPI_Receive+0xd2>
  * @param  Tickstart: tick start value
  * @retval HAL status
  */
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi,  uint32_t Timeout, uint32_t Tickstart)
{
  if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
 80016d0:	68a2      	ldr	r2, [r4, #8]
 80016d2:	f5b2 4f00 	cmp.w	r2, #32768	; 0x8000
 80016d6:	d002      	beq.n	80016de <HAL_SPI_Receive+0x138>
                                               || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
 80016d8:	f5b2 6f80 	cmp.w	r2, #1024	; 0x400
 80016dc:	d103      	bne.n	80016e6 <HAL_SPI_Receive+0x140>
  {
    /* Disable SPI peripheral */
    __HAL_SPI_DISABLE(hspi);
 80016de:	681a      	ldr	r2, [r3, #0]
 80016e0:	f022 0240 	bic.w	r2, r2, #64	; 0x40
 80016e4:	601a      	str	r2, [r3, #0]
  * @retval HAL status
  */
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
 80016e6:	689a      	ldr	r2, [r3, #8]
 80016e8:	f002 0280 	and.w	r2, r2, #128	; 0x80
 80016ec:	b152      	cbz	r2, 8001704 <HAL_SPI_Receive+0x15e>
 80016ee:	e7fa      	b.n	80016e6 <HAL_SPI_Receive+0x140>
  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  if (hspi->State != HAL_SPI_STATE_READY)
  {
    errorcode = HAL_BUSY;
 80016f0:	2002      	movs	r0, #2
  {
    errorcode = HAL_ERROR;
  }

error :
  hspi->State = HAL_SPI_STATE_READY;
 80016f2:	2301      	movs	r3, #1
 80016f4:	f884 305d 	strb.w	r3, [r4, #93]	; 0x5d
  __HAL_UNLOCK(hspi);
 80016f8:	2300      	movs	r3, #0
 80016fa:	f884 305c 	strb.w	r3, [r4, #92]	; 0x5c
  return errorcode;
 80016fe:	e01b      	b.n	8001738 <HAL_SPI_Receive+0x192>
    /* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
    return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
  }

  /* Process Locked */
  __HAL_LOCK(hspi);
 8001700:	2002      	movs	r0, #2
 8001702:	e019      	b.n	8001738 <HAL_SPI_Receive+0x192>
  {
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
    return HAL_TIMEOUT;
  }

  if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
 8001704:	f5b1 7f82 	cmp.w	r1, #260	; 0x104
 8001708:	d106      	bne.n	8001718 <HAL_SPI_Receive+0x172>
 800170a:	68a2      	ldr	r2, [r4, #8]
 800170c:	f5b2 4f00 	cmp.w	r2, #32768	; 0x8000
 8001710:	d007      	beq.n	8001722 <HAL_SPI_Receive+0x17c>
                                               || (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
 8001712:	f5b2 6f80 	cmp.w	r2, #1024	; 0x400
 8001716:	d004      	beq.n	8001722 <HAL_SPI_Receive+0x17c>
    SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
    __HAL_SPI_CLEAR_CRCERRFLAG(hspi);
  }
#endif /* USE_SPI_CRC */

  if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
 8001718:	6e20      	ldr	r0, [r4, #96]	; 0x60
  /* Init tickstart for timeout management*/
  tickstart = HAL_GetTick();

  if (hspi->State != HAL_SPI_STATE_READY)
  {
    errorcode = HAL_BUSY;
 800171a:	3000      	adds	r0, #0
 800171c:	bf18      	it	ne
 800171e:	2001      	movne	r0, #1
 8001720:	e7e7      	b.n	80016f2 <HAL_SPI_Receive+0x14c>
static HAL_StatusTypeDef SPI_WaitFifoStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Fifo, uint32_t State,
                                                       uint32_t Timeout, uint32_t Tickstart)
{
  __IO uint8_t tmpreg;

  while ((hspi->Instance->SR & Fifo) != State)
 8001722:	689a      	ldr	r2, [r3, #8]
 8001724:	f412 6fc0 	tst.w	r2, #1536	; 0x600
 8001728:	d0f6      	beq.n	8001718 <HAL_SPI_Receive+0x172>
  {
    if ((Fifo == SPI_SR_FRLVL) && (State == SPI_FRLVL_EMPTY))
    {
      tmpreg = *((__IO uint8_t *)&hspi->Instance->DR);
 800172a:	7b1a      	ldrb	r2, [r3, #12]
 800172c:	b2d2      	uxtb	r2, r2
 800172e:	f88d 200f 	strb.w	r2, [sp, #15]
      /* To avoid GCC warning */
      UNUSED(tmpreg);
 8001732:	f89d 200f 	ldrb.w	r2, [sp, #15]
 8001736:	e7f4      	b.n	8001722 <HAL_SPI_Receive+0x17c>

error :
  hspi->State = HAL_SPI_STATE_READY;
  __HAL_UNLOCK(hspi);
  return errorcode;
}
 8001738:	b004      	add	sp, #16
 800173a:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
	...

08001740 <checksum_more>:

// checksum_more()
//
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
 8001740:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
    // do a nice progress bar as it works.
    while(len) {
        int here = MIN(len, 8196);
        int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;

        oled_show_progress(screen_verify, percent);
 8001744:	f8df a054 	ldr.w	sl, [pc, #84]	; 800179c <checksum_more+0x5c>

// checksum_more()
//
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
 8001748:	4680      	mov	r8, r0
 800174a:	460e      	mov	r6, r1
 800174c:	4617      	mov	r7, r2
 800174e:	461c      	mov	r4, r3
    // do a nice progress bar as it works.
    while(len) {
        int here = MIN(len, 8196);
 8001750:	f242 0904 	movw	r9, #8196	; 0x2004
//
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
    // do a nice progress bar as it works.
    while(len) {
 8001754:	b1f4      	cbz	r4, 8001794 <checksum_more+0x54>
        int here = MIN(len, 8196);
        int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;

        oled_show_progress(screen_verify, percent);
 8001756:	6831      	ldr	r1, [r6, #0]
 8001758:	480f      	ldr	r0, [pc, #60]	; (8001798 <checksum_more+0x58>)
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
    // do a nice progress bar as it works.
    while(len) {
        int here = MIN(len, 8196);
 800175a:	454c      	cmp	r4, r9
        int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;

        oled_show_progress(screen_verify, percent);
 800175c:	f04f 0364 	mov.w	r3, #100	; 0x64
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
    // do a nice progress bar as it works.
    while(len) {
        int here = MIN(len, 8196);
 8001760:	4625      	mov	r5, r4
        int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;

        oled_show_progress(screen_verify, percent);
 8001762:	fb03 f101 	mul.w	r1, r3, r1
    static void
checksum_more(SHA256_CTX *ctx, uint32_t *total, const uint8_t *addr, int len)
{
    // do a nice progress bar as it works.
    while(len) {
        int here = MIN(len, 8196);
 8001766:	bfa8      	it	ge
 8001768:	464d      	movge	r5, r9
        int percent = ((*total) * 100) / TOTAL_CHECKSUM_LEN;

        oled_show_progress(screen_verify, percent);
 800176a:	fbb1 f1fa 	udiv	r1, r1, sl
 800176e:	f7ff faa3 	bl	8000cb8 <oled_show_progress>
        sha256_update(ctx, addr, here);
 8001772:	4639      	mov	r1, r7
 8001774:	462a      	mov	r2, r5
 8001776:	4640      	mov	r0, r8
 8001778:	f003 fe44 	bl	8005404 <sha256_update>

        *total += here;
 800177c:	6833      	ldr	r3, [r6, #0]
 800177e:	442b      	add	r3, r5
 8001780:	6033      	str	r3, [r6, #0]
        addr += here;
 8001782:	442f      	add	r7, r5
        len -= here;
 8001784:	1b64      	subs	r4, r4, r5

        if(dfu_button_pressed()) dfu_by_request();
 8001786:	f001 fcb1 	bl	80030ec <dfu_button_pressed>
 800178a:	2800      	cmp	r0, #0
 800178c:	d0e2      	beq.n	8001754 <checksum_more+0x14>
 800178e:	f7fe febb 	bl	8000508 <dfu_by_request>
 8001792:	e7df      	b.n	8001754 <checksum_more+0x14>
    }
}
 8001794:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
 8001798:	08006ad6 	.word	0x08006ad6
 800179c:	0010741c 	.word	0x0010741c

080017a0 <checksum_flash>:

// checksum_flash()
//
    void
checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
{
 80017a0:	b570      	push	{r4, r5, r6, lr}
 80017a2:	b0a6      	sub	sp, #152	; 0x98
 80017a4:	4606      	mov	r6, r0
    const uint8_t *start = (const uint8_t *)FIRMWARE_START;

    SHA256_CTX  ctx;
    uint32_t    total_len = 0;
 80017a6:	2300      	movs	r3, #0
    uint8_t first[32];

    sha256_init(&ctx);
 80017a8:	a80a      	add	r0, sp, #40	; 0x28
    // start of firmware (just after we end) to header
    checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);

    // from after header to end
    checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE, 
                            FW_HDR->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));
 80017aa:	4d3d      	ldr	r5, [pc, #244]	; (80018a0 <checksum_flash+0x100>)
checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
{
    const uint8_t *start = (const uint8_t *)FIRMWARE_START;

    SHA256_CTX  ctx;
    uint32_t    total_len = 0;
 80017ac:	9301      	str	r3, [sp, #4]

// checksum_flash()
//
    void
checksum_flash(uint8_t fw_digest[32], uint8_t world_digest[32])
{
 80017ae:	460c      	mov	r4, r1

    SHA256_CTX  ctx;
    uint32_t    total_len = 0;
    uint8_t first[32];

    sha256_init(&ctx);
 80017b0:	f003 fdfe 	bl	80053b0 <sha256_init>

    // start of firmware (just after we end) to header
    checksum_more(&ctx, &total_len, start, FW_HEADER_OFFSET + FW_HEADER_SIZE - 64);
 80017b4:	f44f 537f 	mov.w	r3, #16320	; 0x3fc0
 80017b8:	4a3a      	ldr	r2, [pc, #232]	; (80018a4 <checksum_flash+0x104>)
 80017ba:	a901      	add	r1, sp, #4
 80017bc:	a80a      	add	r0, sp, #40	; 0x28
 80017be:	f7ff ffbf 	bl	8001740 <checksum_more>

    // from after header to end
    checksum_more(&ctx, &total_len, start + FW_HEADER_OFFSET + FW_HEADER_SIZE, 
 80017c2:	69ab      	ldr	r3, [r5, #24]
 80017c4:	4a38      	ldr	r2, [pc, #224]	; (80018a8 <checksum_flash+0x108>)
 80017c6:	f5a3 4380 	sub.w	r3, r3, #16384	; 0x4000
 80017ca:	a901      	add	r1, sp, #4
 80017cc:	a80a      	add	r0, sp, #40	; 0x28
 80017ce:	f7ff ffb7 	bl	8001740 <checksum_more>
                            FW_HDR->firmware_length - (FW_HEADER_OFFSET + FW_HEADER_SIZE));

    sha256_final(&ctx, first);
 80017d2:	a902      	add	r1, sp, #8
 80017d4:	a80a      	add	r0, sp, #40	; 0x28
 80017d6:	f003 fe33 	bl	8005440 <sha256_final>

    // double SHA256
    sha256_init(&ctx);
 80017da:	a80a      	add	r0, sp, #40	; 0x28
 80017dc:	f003 fde8 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, first, sizeof(first));
 80017e0:	2220      	movs	r2, #32
 80017e2:	a902      	add	r1, sp, #8
 80017e4:	a80a      	add	r0, sp, #40	; 0x28
 80017e6:	f003 fe0d 	bl	8005404 <sha256_update>
    sha256_final(&ctx, fw_digest);
 80017ea:	4631      	mov	r1, r6
 80017ec:	a80a      	add	r0, sp, #40	; 0x28
 80017ee:	f003 fe27 	bl	8005440 <sha256_final>

    // start over, and get the rest of flash. All of it.
    sha256_init(&ctx);
 80017f2:	a80a      	add	r0, sp, #40	; 0x28
 80017f4:	f003 fddc 	bl	80053b0 <sha256_init>

    // .. and chain in what we have so far
    sha256_update(&ctx, fw_digest, 32);
 80017f8:	2220      	movs	r2, #32
 80017fa:	4631      	mov	r1, r6
 80017fc:	a80a      	add	r0, sp, #40	; 0x28
 80017fe:	f003 fe01 	bl	8005404 <sha256_update>

    // bootloader, including pairing secret area.
    const uint8_t *base = (const uint8_t *)BL_FLASH_BASE;
    checksum_more(&ctx, &total_len, base, start-base);
 8001802:	f44f 4300 	mov.w	r3, #32768	; 0x8000
 8001806:	f04f 6200 	mov.w	r2, #134217728	; 0x8000000
 800180a:	a901      	add	r1, sp, #4
 800180c:	a80a      	add	r0, sp, #40	; 0x28
 800180e:	f7ff ff97 	bl	8001740 <checksum_more>

    // probably-blank area after firmware, and filesystem area
    const uint8_t *fs = start + FW_HDR->firmware_length;
 8001812:	69aa      	ldr	r2, [r5, #24]
 8001814:	f102 6200 	add.w	r2, r2, #134217728	; 0x8000000
 8001818:	f502 4200 	add.w	r2, r2, #32768	; 0x8000
    const uint8_t *last = base + MAIN_FLASH_SIZE;
    checksum_more(&ctx, &total_len, fs, last-fs);
 800181c:	f1c2 6301 	rsb	r3, r2, #135266304	; 0x8100000
 8001820:	a901      	add	r1, sp, #4
 8001822:	a80a      	add	r0, sp, #40	; 0x28
 8001824:	f7ff ff8c 	bl	8001740 <checksum_more>

    // OTP area
    checksum_more(&ctx, &total_len, (void *)0x1fff7000, 0x400);
 8001828:	f44f 6380 	mov.w	r3, #1024	; 0x400
 800182c:	4a1f      	ldr	r2, [pc, #124]	; (80018ac <checksum_flash+0x10c>)
 800182e:	a901      	add	r1, sp, #4
 8001830:	a80a      	add	r0, sp, #40	; 0x28
 8001832:	f7ff ff85 	bl	8001740 <checksum_more>

    // "just in case" ... the option bytes (2 banks)
    checksum_more(&ctx, &total_len, (void *)0x1fff7800, 0x28);
 8001836:	2328      	movs	r3, #40	; 0x28
 8001838:	eb0d 0003 	add.w	r0, sp, r3
 800183c:	4a1c      	ldr	r2, [pc, #112]	; (80018b0 <checksum_flash+0x110>)
 800183e:	a901      	add	r1, sp, #4
 8001840:	f7ff ff7e 	bl	8001740 <checksum_more>
    checksum_more(&ctx, &total_len, (void *)0x1ffff800, 0x28);
 8001844:	2328      	movs	r3, #40	; 0x28
 8001846:	eb0d 0003 	add.w	r0, sp, r3
 800184a:	4a1a      	ldr	r2, [pc, #104]	; (80018b4 <checksum_flash+0x114>)
 800184c:	a901      	add	r1, sp, #4
 800184e:	f7ff ff77 	bl	8001740 <checksum_more>

    // System ROM (they say it can't change, but clearly
    // implemented as flash cells)
    checksum_more(&ctx, &total_len, (void *)0x1fff0000, 0x7000);
 8001852:	f44f 43e0 	mov.w	r3, #28672	; 0x7000
 8001856:	4a18      	ldr	r2, [pc, #96]	; (80018b8 <checksum_flash+0x118>)
 8001858:	a901      	add	r1, sp, #4
 800185a:	a80a      	add	r0, sp, #40	; 0x28
 800185c:	f7ff ff70 	bl	8001740 <checksum_more>

    // device serial number, just for kicks
    checksum_more(&ctx, &total_len, (void *)0x1fff7590, 12);
 8001860:	230c      	movs	r3, #12
 8001862:	4a16      	ldr	r2, [pc, #88]	; (80018bc <checksum_flash+0x11c>)
 8001864:	a901      	add	r1, sp, #4
 8001866:	a80a      	add	r0, sp, #40	; 0x28
 8001868:	f7ff ff6a 	bl	8001740 <checksum_more>

    ASSERT(total_len == TOTAL_CHECKSUM_LEN);
 800186c:	9a01      	ldr	r2, [sp, #4]
 800186e:	4b14      	ldr	r3, [pc, #80]	; (80018c0 <checksum_flash+0x120>)
 8001870:	429a      	cmp	r2, r3
 8001872:	d002      	beq.n	800187a <checksum_flash+0xda>
 8001874:	4813      	ldr	r0, [pc, #76]	; (80018c4 <checksum_flash+0x124>)
 8001876:	f7fe fda9 	bl	80003cc <fatal_error>
    
    sha256_final(&ctx, world_digest);
 800187a:	4621      	mov	r1, r4
 800187c:	a80a      	add	r0, sp, #40	; 0x28
 800187e:	f003 fddf 	bl	8005440 <sha256_final>

    // double SHA256 (a bitcoin fetish)
    sha256_init(&ctx);
 8001882:	a80a      	add	r0, sp, #40	; 0x28
 8001884:	f003 fd94 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, world_digest, 32);
 8001888:	2220      	movs	r2, #32
 800188a:	4621      	mov	r1, r4
 800188c:	a80a      	add	r0, sp, #40	; 0x28
 800188e:	f003 fdb9 	bl	8005404 <sha256_update>
    sha256_final(&ctx, world_digest);
 8001892:	4621      	mov	r1, r4
 8001894:	a80a      	add	r0, sp, #40	; 0x28
 8001896:	f003 fdd3 	bl	8005440 <sha256_final>
}
 800189a:	b026      	add	sp, #152	; 0x98
 800189c:	bd70      	pop	{r4, r5, r6, pc}
 800189e:	bf00      	nop
 80018a0:	0800bf80 	.word	0x0800bf80
 80018a4:	08008000 	.word	0x08008000
 80018a8:	0800c000 	.word	0x0800c000
 80018ac:	1fff7000 	.word	0x1fff7000
 80018b0:	1fff7800 	.word	0x1fff7800
 80018b4:	1ffff800 	.word	0x1ffff800
 80018b8:	1fff0000 	.word	0x1fff0000
 80018bc:	1fff7590 	.word	0x1fff7590
 80018c0:	0010741c 	.word	0x0010741c
 80018c4:	08006960 	.word	0x08006960

080018c8 <get_min_version>:
// Scan the OTP area and determine what the current min-version (timestamp)
// we can allow. All zeros if any if okay.
//
    void
get_min_version(uint8_t min_version[8])
{
 80018c8:	b570      	push	{r4, r5, r6, lr}
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    memset(min_version, 0, 8);
 80018ca:	2300      	movs	r3, #0
// we can allow. All zeros if any if okay.
//
    void
get_min_version(uint8_t min_version[8])
{
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;
 80018cc:	4c0b      	ldr	r4, [pc, #44]	; (80018fc <get_min_version+0x34>)

    memset(min_version, 0, 8);

    for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
 80018ce:	4e0c      	ldr	r6, [pc, #48]	; (8001900 <get_min_version+0x38>)
    void
get_min_version(uint8_t min_version[8])
{
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    memset(min_version, 0, 8);
 80018d0:	6003      	str	r3, [r0, #0]
// Scan the OTP area and determine what the current min-version (timestamp)
// we can allow. All zeros if any if okay.
//
    void
get_min_version(uint8_t min_version[8])
{
 80018d2:	4605      	mov	r5, r0
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    memset(min_version, 0, 8);
 80018d4:	6043      	str	r3, [r0, #4]
        // is it programmed?
        if(otp[0] == 0xff) continue;

        // is it a timestamp value?
        if(otp[0] >= 0x40) continue;
        if(otp[0] < 0x10) continue;
 80018d6:	7823      	ldrb	r3, [r4, #0]
 80018d8:	3b10      	subs	r3, #16
 80018da:	2b2f      	cmp	r3, #47	; 0x2f
 80018dc:	d80a      	bhi.n	80018f4 <get_min_version+0x2c>

        if(memcmp(otp, min_version, 8) > 0) {
 80018de:	4629      	mov	r1, r5
 80018e0:	2208      	movs	r2, #8
 80018e2:	4620      	mov	r0, r4
 80018e4:	f004 ffd1 	bl	800688a <memcmp>
 80018e8:	2800      	cmp	r0, #0
            memcpy(min_version, otp, 8);
 80018ea:	bfc1      	itttt	gt
 80018ec:	4623      	movgt	r3, r4
 80018ee:	cb03      	ldmiagt	r3!, {r0, r1}
 80018f0:	6028      	strgt	r0, [r5, #0]
 80018f2:	6069      	strgt	r1, [r5, #4]
{
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    memset(min_version, 0, 8);

    for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
 80018f4:	3408      	adds	r4, #8
 80018f6:	42b4      	cmp	r4, r6
 80018f8:	d1ed      	bne.n	80018d6 <get_min_version+0xe>

        if(memcmp(otp, min_version, 8) > 0) {
            memcpy(min_version, otp, 8);
        }
    }
}
 80018fa:	bd70      	pop	{r4, r5, r6, pc}
 80018fc:	1fff7000 	.word	0x1fff7000
 8001900:	1fff7400 	.word	0x1fff7400

08001904 <check_is_downgrade>:

// check_is_downgrade()
//
    bool
check_is_downgrade(const uint8_t timestamp[8])
{
 8001904:	b513      	push	{r0, r1, r4, lr}
 8001906:	4604      	mov	r4, r0
    // look at FW_HDR->timestamp and compare to a growing list in main flash OTP
    uint8_t min[8];

    get_min_version(min);
 8001908:	4668      	mov	r0, sp
 800190a:	f7ff ffdd 	bl	80018c8 <get_min_version>

    return (memcmp(timestamp, min, 8) < 0);
 800190e:	2208      	movs	r2, #8
 8001910:	4669      	mov	r1, sp
 8001912:	4620      	mov	r0, r4
 8001914:	f004 ffb9 	bl	800688a <memcmp>
}
 8001918:	0fc0      	lsrs	r0, r0, #31
 800191a:	b002      	add	sp, #8
 800191c:	bd10      	pop	{r4, pc}
	...

08001920 <check_factory_key>:

// check_factory_key()
//
    void
check_factory_key(uint32_t pubkey_num)
{
 8001920:	b510      	push	{r4, lr}
    if(IS_FACTORY_KEY(pubkey_num)) return;
 8001922:	b950      	cbnz	r0, 800193a <check_factory_key+0x1a>
 8001924:	4604      	mov	r4, r0
#else
    const int wait = 10;
#endif
    
    for(int i=0; i < wait; i++) {
        oled_show_progress(screen_devmode, (i*100)/wait);
 8001926:	4621      	mov	r1, r4
 8001928:	4804      	ldr	r0, [pc, #16]	; (800193c <check_factory_key+0x1c>)
 800192a:	f7ff f9c5 	bl	8000cb8 <oled_show_progress>
    const int wait = 100;
#else
    const int wait = 10;
#endif
    
    for(int i=0; i < wait; i++) {
 800192e:	3401      	adds	r4, #1
        oled_show_progress(screen_devmode, (i*100)/wait);

        delay_ms(250);
 8001930:	20fa      	movs	r0, #250	; 0xfa
 8001932:	f001 fb7b 	bl	800302c <delay_ms>
    const int wait = 100;
#else
    const int wait = 10;
#endif
    
    for(int i=0; i < wait; i++) {
 8001936:	2c64      	cmp	r4, #100	; 0x64
 8001938:	d1f5      	bne.n	8001926 <check_factory_key+0x6>
 800193a:	bd10      	pop	{r4, pc}
 800193c:	08006dc5 	.word	0x08006dc5

08001940 <verify_header>:
// verify_header()
//
    bool
verify_header(const coldcardFirmwareHeader_t *hdr)
{
    if(hdr->magic_value != FW_HEADER_MAGIC) goto fail;
 8001940:	6802      	ldr	r2, [r0, #0]
 8001942:	4b0c      	ldr	r3, [pc, #48]	; (8001974 <verify_header+0x34>)
 8001944:	429a      	cmp	r2, r3
 8001946:	d112      	bne.n	800196e <verify_header+0x2e>
    if(hdr->version_string[0] == 0x0) goto fail;
 8001948:	7b03      	ldrb	r3, [r0, #12]
 800194a:	b173      	cbz	r3, 800196a <verify_header+0x2a>
    if(hdr->timestamp[0] >= 0x40) goto fail;        // 22 yr product lifetime
 800194c:	7903      	ldrb	r3, [r0, #4]
 800194e:	2b3f      	cmp	r3, #63	; 0x3f
 8001950:	d80d      	bhi.n	800196e <verify_header+0x2e>
    if(hdr->firmware_length < FW_MIN_LENGTH) goto fail;
 8001952:	6983      	ldr	r3, [r0, #24]
 8001954:	f5a3 2380 	sub.w	r3, r3, #262144	; 0x40000
 8001958:	f5b3 2f38 	cmp.w	r3, #753664	; 0xb8000
 800195c:	d807      	bhi.n	800196e <verify_header+0x2e>
    if(hdr->firmware_length > FW_MAX_LENGTH) goto fail;
    if(hdr->pubkey_num >= NUM_KNOWN_PUBKEYS) goto fail;
 800195e:	6940      	ldr	r0, [r0, #20]
 8001960:	2805      	cmp	r0, #5
 8001962:	bf8c      	ite	hi
 8001964:	2000      	movhi	r0, #0
 8001966:	2001      	movls	r0, #1
 8001968:	4770      	bx	lr

    return true;
fail:
    return false;
 800196a:	4618      	mov	r0, r3
 800196c:	4770      	bx	lr
 800196e:	2000      	movs	r0, #0
}
 8001970:	4770      	bx	lr
 8001972:	bf00      	nop
 8001974:	cc001234 	.word	0xcc001234

08001978 <verify_firmware>:

// verify_firmware()
//
    void
verify_firmware(void)
{
 8001978:	b530      	push	{r4, r5, lr}
    STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE);

    // watch for unprogrammed header. and some 
    if(FW_HDR->version_string[0] == 0xff) goto blank;
 800197a:	4c18      	ldr	r4, [pc, #96]	; (80019dc <verify_firmware+0x64>)
 800197c:	7b23      	ldrb	r3, [r4, #12]
 800197e:	2bff      	cmp	r3, #255	; 0xff

// verify_firmware()
//
    void
verify_firmware(void)
{
 8001980:	b093      	sub	sp, #76	; 0x4c
    STATIC_ASSERT(sizeof(coldcardFirmwareHeader_t) == FW_HEADER_SIZE);

    // watch for unprogrammed header. and some 
    if(FW_HDR->version_string[0] == 0xff) goto blank;
 8001982:	d023      	beq.n	80019cc <verify_firmware+0x54>
    if(!verify_header(FW_HDR)) goto fail;
 8001984:	4620      	mov	r0, r4
 8001986:	f7ff ffdb 	bl	8001940 <verify_header>
 800198a:	b1e8      	cbz	r0, 80019c8 <verify_firmware+0x50>

    // measure checksum
    uint8_t fw_check[32], world_check[32];
    checksum_flash(fw_check, world_check);
 800198c:	a90a      	add	r1, sp, #40	; 0x28
 800198e:	a802      	add	r0, sp, #8
 8001990:	f7ff ff06 	bl	80017a0 <checksum_flash>

    // verify the signature
    // - use pubkey_num to pick a specific key
    // - maybe show warning if dev key
    int ok = uECC_verify(approved_pubkeys[FW_HDR->pubkey_num], fw_check, 32,
 8001994:	4b12      	ldr	r3, [pc, #72]	; (80019e0 <verify_firmware+0x68>)
 8001996:	6965      	ldr	r5, [r4, #20]
 8001998:	eb03 1585 	add.w	r5, r3, r5, lsl #6
 800199c:	f004 fc16 	bl	80061cc <uECC_secp256k1>
 80019a0:	4b10      	ldr	r3, [pc, #64]	; (80019e4 <verify_firmware+0x6c>)
 80019a2:	9000      	str	r0, [sp, #0]
 80019a4:	2220      	movs	r2, #32
 80019a6:	a902      	add	r1, sp, #8
 80019a8:	4628      	mov	r0, r5
 80019aa:	f004 fdad 	bl	8006508 <uECC_verify>
                                    FW_HDR->signature, uECC_secp256k1());
    if(!ok) goto fail;
 80019ae:	b158      	cbz	r0, 80019c8 <verify_firmware+0x50>
 
    // Push the hash to the 508a which might make the Genuine light green,
    // but only if we arrived at same hash before. It decides.
    int not_green = ae_set_gpio_secure(world_check);
 80019b0:	a80a      	add	r0, sp, #40	; 0x28
 80019b2:	f001 f9bd 	bl	8002d30 <ae_set_gpio_secure>

    // maybe show big warning if not an "approved" key
    if(not_green) {
 80019b6:	b110      	cbz	r0, 80019be <verify_firmware+0x46>
        check_factory_key(FW_HDR->pubkey_num);
 80019b8:	6960      	ldr	r0, [r4, #20]
 80019ba:	f7ff ffb1 	bl	8001920 <check_factory_key>
    }

    oled_show_progress(screen_verify, 100);
 80019be:	2164      	movs	r1, #100	; 0x64
 80019c0:	4809      	ldr	r0, [pc, #36]	; (80019e8 <verify_firmware+0x70>)
 80019c2:	f7ff f979 	bl	8000cb8 <oled_show_progress>

    return;
 80019c6:	e006      	b.n	80019d6 <verify_firmware+0x5e>

fail:
    oled_show(screen_corrupt);
 80019c8:	4808      	ldr	r0, [pc, #32]	; (80019ec <verify_firmware+0x74>)
 80019ca:	e000      	b.n	80019ce <verify_firmware+0x56>
    enter_dfu();
    return;

blank:
    oled_show(screen_dfu);
 80019cc:	4808      	ldr	r0, [pc, #32]	; (80019f0 <verify_firmware+0x78>)
 80019ce:	f7ff f933 	bl	8000c38 <oled_show>
    enter_dfu();
 80019d2:	f7fe fd49 	bl	8000468 <enter_dfu>
    return;
}
 80019d6:	b013      	add	sp, #76	; 0x4c
 80019d8:	bd30      	pop	{r4, r5, pc}
 80019da:	bf00      	nop
 80019dc:	0800bf80 	.word	0x0800bf80
 80019e0:	080070b0 	.word	0x080070b0
 80019e4:	0800bfc0 	.word	0x0800bfc0
 80019e8:	08006ad6 	.word	0x08006ad6
 80019ec:	08006ff1 	.word	0x08006ff1
 80019f0:	08006cc3 	.word	0x08006cc3

080019f4 <systick_setup>:
    void
systick_setup(void)
{
    const uint32_t ticks = HCLK_FREQUENCY/1000;

    SysTick->LOAD = (ticks - 1);
 80019f4:	4b03      	ldr	r3, [pc, #12]	; (8001a04 <systick_setup+0x10>)
 80019f6:	4a04      	ldr	r2, [pc, #16]	; (8001a08 <systick_setup+0x14>)
 80019f8:	605a      	str	r2, [r3, #4]
    SysTick->VAL = 0;
 80019fa:	2200      	movs	r2, #0
 80019fc:	609a      	str	r2, [r3, #8]
    SysTick->CTRL = SYSTICK_CLKSOURCE_HCLK | SysTick_CTRL_ENABLE_Msk;
 80019fe:	2205      	movs	r2, #5
 8001a00:	601a      	str	r2, [r3, #0]
 8001a02:	4770      	bx	lr
 8001a04:	e000e010 	.word	0xe000e010
 8001a08:	0001387f 	.word	0x0001387f

08001a0c <clocks_setup>:

// clocks_setup()
//
    void
clocks_setup(void)
{
 8001a0c:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;

    // Configure LSE Drive Capability
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
 8001a10:	4d2b      	ldr	r5, [pc, #172]	; (8001ac0 <clocks_setup+0xb4>)
 8001a12:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90

// clocks_setup()
//
    void
clocks_setup(void)
{
 8001a16:	b0b9      	sub	sp, #228	; 0xe4
    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;

    // Configure LSE Drive Capability
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
 8001a18:	f023 0318 	bic.w	r3, r3, #24
 8001a1c:	f8c5 3090 	str.w	r3, [r5, #144]	; 0x90

    // Enable HSE Oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 8001a20:	2301      	movs	r3, #1
 8001a22:	9305      	str	r3, [sp, #20]

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 8001a24:	f44f 3380 	mov.w	r3, #65536	; 0x10000
    RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
    RCC_OscInitStruct.MSIState = RCC_MSI_OFF;

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 8001a28:	2703      	movs	r7, #3
    __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

    // Enable HSE Oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
 8001a2a:	9306      	str	r3, [sp, #24]
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

    // Select PLL as system clock source and configure
    // the HCLK, PCLK1 and PCLK2 clocks dividers
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK 
 8001a2c:	230f      	movs	r3, #15

    // Enable HSE Oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
 8001a2e:	2400      	movs	r4, #0
    RCC_OscInitStruct.MSIState = RCC_MSI_OFF;

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 8001a30:	2602      	movs	r6, #2

    // Select PLL as system clock source and configure
    // the HCLK, PCLK1 and PCLK2 clocks dividers
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK 
                                    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 8001a32:	e88d 0088 	stmia.w	sp, {r3, r7}

    RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
    RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN;
    RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP;
 8001a36:	f04f 0807 	mov.w	r8, #7
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK 
                                    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

    RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
    RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN;
 8001a3a:	2328      	movs	r3, #40	; 0x28
    RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP;
    RCC_OscInitStruct.PLL.PLLQ = CKCC_CLK_PLLQ;
 8001a3c:	f04f 0904 	mov.w	r9, #4

    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 8001a40:	a805      	add	r0, sp, #20
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK 
                                    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

    RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
    RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN;
 8001a42:	9312      	str	r3, [sp, #72]	; 0x48

    // Enable HSE Oscillator and activate PLL with HSE as source
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.LSEState = RCC_LSE_OFF;
 8001a44:	9407      	str	r4, [sp, #28]
    RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
 8001a46:	940b      	str	r4, [sp, #44]	; 0x2c

    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 8001a48:	9710      	str	r7, [sp, #64]	; 0x40
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 8001a4a:	960f      	str	r6, [sp, #60]	; 0x3c
    // the HCLK, PCLK1 and PCLK2 clocks dividers
    RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK 
                                    | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

    RCC_OscInitStruct.PLL.PLLM = CKCC_CLK_PLLM;
 8001a4c:	9611      	str	r6, [sp, #68]	; 0x44
    RCC_OscInitStruct.PLL.PLLN = CKCC_CLK_PLLN;
    RCC_OscInitStruct.PLL.PLLP = CKCC_CLK_PLLP;
 8001a4e:	f8cd 804c 	str.w	r8, [sp, #76]	; 0x4c
    RCC_OscInitStruct.PLL.PLLQ = CKCC_CLK_PLLQ;
 8001a52:	f8cd 9050 	str.w	r9, [sp, #80]	; 0x50
    RCC_OscInitStruct.PLL.PLLR = CKCC_CLK_PLLR;
 8001a56:	9615      	str	r6, [sp, #84]	; 0x54

    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 8001a58:	9402      	str	r4, [sp, #8]
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 8001a5a:	9403      	str	r4, [sp, #12]
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 8001a5c:	9404      	str	r4, [sp, #16]

    HAL_RCC_OscConfig(&RCC_OscInitStruct);
 8001a5e:	f002 faad 	bl	8003fbc <HAL_RCC_OscConfig>

    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
 8001a62:	4649      	mov	r1, r9
 8001a64:	4668      	mov	r0, sp
 8001a66:	f002 fcb9 	bl	80043dc <HAL_RCC_ClockConfig>

    // DIS-able MSI-Hardware auto calibration mode with LSE
    CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN);
 8001a6a:	682b      	ldr	r3, [r5, #0]
 8001a6c:	f023 0304 	bic.w	r3, r3, #4
 8001a70:	602b      	str	r3, [r5, #0]

    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1
 8001a72:	4b14      	ldr	r3, [pc, #80]	; (8001ac4 <clocks_setup+0xb8>)
 8001a74:	9316      	str	r3, [sp, #88]	; 0x58
    PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
    // PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is
    // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz.
    //
    PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
 8001a76:	f04f 5380 	mov.w	r3, #268435456	; 0x10000000
 8001a7a:	9334      	str	r3, [sp, #208]	; 0xd0
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
 8001a7c:	f04f 6380 	mov.w	r3, #67108864	; 0x4000000
 8001a80:	9331      	str	r3, [sp, #196]	; 0xc4
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;
 8001a82:	9333      	str	r3, [sp, #204]	; 0xcc

    PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
 8001a84:	2318      	movs	r3, #24
    // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz.
    //
    PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 8001a86:	f44f 7280 	mov.w	r2, #256	; 0x100
    PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;

    PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
 8001a8a:	9319      	str	r3, [sp, #100]	; 0x64
    PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
                                                 |RCC_PLLSAI1_48M2CLK
                                                 |RCC_PLLSAI1_ADC1CLK;

    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 8001a8c:	a816      	add	r0, sp, #88	; 0x58
    PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
 8001a8e:	4b0e      	ldr	r3, [pc, #56]	; (8001ac8 <clocks_setup+0xbc>)
    // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz.
    //
    PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 8001a90:	9237      	str	r2, [sp, #220]	; 0xdc
    PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
 8001a92:	931d      	str	r3, [sp, #116]	; 0x74
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1|RCC_PERIPHCLK_I2C1
                                              |RCC_PERIPHCLK_USB |RCC_PERIPHCLK_ADC
                                              |RCC_PERIPHCLK_RNG |RCC_PERIPHCLK_RTC;

    PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
 8001a94:	942a      	str	r4, [sp, #168]	; 0xa8
    // PLLSAI is used to clock USB, ADC, I2C1 and RNG. The frequency is
    // HSE(8MHz)/PLLM(2)*PLLSAI1N(24)/PLLSAIQ(2) = 48MHz.
    //
    PeriphClkInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
 8001a96:	942f      	str	r4, [sp, #188]	; 0xbc
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
    PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
    PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLLSAI1;

    PeriphClkInitStruct.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
 8001a98:	9717      	str	r7, [sp, #92]	; 0x5c
    PeriphClkInitStruct.PLLSAI1.PLLSAI1M = 2;
 8001a9a:	9618      	str	r6, [sp, #96]	; 0x60
    PeriphClkInitStruct.PLLSAI1.PLLSAI1N = 24;
    PeriphClkInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
 8001a9c:	f8cd 8068 	str.w	r8, [sp, #104]	; 0x68
    PeriphClkInitStruct.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
 8001aa0:	961b      	str	r6, [sp, #108]	; 0x6c
    PeriphClkInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
 8001aa2:	961c      	str	r6, [sp, #112]	; 0x70
    PeriphClkInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK
                                                 |RCC_PLLSAI1_48M2CLK
                                                 |RCC_PLLSAI1_ADC1CLK;

    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
 8001aa4:	f002 fe9e 	bl	80047e4 <HAL_RCCEx_PeriphCLKConfig>

    __HAL_RCC_RTC_ENABLE();
 8001aa8:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90
 8001aac:	f443 4300 	orr.w	r3, r3, #32768	; 0x8000
 8001ab0:	f8c5 3090 	str.w	r3, [r5, #144]	; 0x90

    // setup SYSTICK, but we don't have the irq hooked up and not using HAL
    systick_setup();
 8001ab4:	f7ff ff9e 	bl	80019f4 <systick_setup>
}
 8001ab8:	b039      	add	sp, #228	; 0xe4
 8001aba:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}
 8001abe:	bf00      	nop
 8001ac0:	40021000 	.word	0x40021000
 8001ac4:	00066840 	.word	0x00066840
 8001ac8:	01110000 	.word	0x01110000

08001acc <flash_ob_lock.part.1>:
    } else {

        // write changes to OB flash bytes

        // Set OPTSTRT bit
        SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
 8001acc:	4b36      	ldr	r3, [pc, #216]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001ace:	695a      	ldr	r2, [r3, #20]
 8001ad0:	f442 3200 	orr.w	r2, r2, #131072	; 0x20000
 8001ad4:	615a      	str	r2, [r3, #20]
 8001ad6:	461a      	mov	r2, r3
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
 8001ad8:	6911      	ldr	r1, [r2, #16]
 8001ada:	4b33      	ldr	r3, [pc, #204]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001adc:	03c8      	lsls	r0, r1, #15
 8001ade:	d4fb      	bmi.n	8001ad8 <flash_ob_lock.part.1+0xc>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
 8001ae0:	691a      	ldr	r2, [r3, #16]
 8001ae2:	0791      	lsls	r1, r2, #30
 8001ae4:	d41e      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
 8001ae6:	691a      	ldr	r2, [r3, #16]
 8001ae8:	0712      	lsls	r2, r2, #28
 8001aea:	d41b      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001aec:	691a      	ldr	r2, [r3, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
 8001aee:	06d0      	lsls	r0, r2, #27
 8001af0:	d418      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001af2:	691a      	ldr	r2, [r3, #16]
 8001af4:	0691      	lsls	r1, r2, #26
 8001af6:	d415      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001af8:	691a      	ldr	r2, [r3, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001afa:	0652      	lsls	r2, r2, #25
 8001afc:	d412      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001afe:	691a      	ldr	r2, [r3, #16]
 8001b00:	0610      	lsls	r0, r2, #24
 8001b02:	d40f      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b04:	691a      	ldr	r2, [r3, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001b06:	05d1      	lsls	r1, r2, #23
 8001b08:	d40c      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b0a:	691a      	ldr	r2, [r3, #16]
 8001b0c:	0592      	lsls	r2, r2, #22
 8001b0e:	d409      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b10:	691b      	ldr	r3, [r3, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b12:	0458      	lsls	r0, r3, #17
 8001b14:	d406      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b16:	4b24      	ldr	r3, [pc, #144]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b18:	691a      	ldr	r2, [r3, #16]
 8001b1a:	0411      	lsls	r1, r2, #16
 8001b1c:	d402      	bmi.n	8001b24 <flash_ob_lock.part.1+0x58>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
 8001b1e:	699a      	ldr	r2, [r3, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b20:	2a00      	cmp	r2, #0
 8001b22:	da02      	bge.n	8001b2a <flash_ob_lock.part.1+0x5e>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
 8001b24:	4b20      	ldr	r3, [pc, #128]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b26:	691b      	ldr	r3, [r3, #16]
 8001b28:	e004      	b.n	8001b34 <flash_ob_lock.part.1+0x68>
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
 8001b2a:	691a      	ldr	r2, [r3, #16]
 8001b2c:	07d2      	lsls	r2, r2, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
 8001b2e:	bf44      	itt	mi
 8001b30:	2201      	movmi	r2, #1
 8001b32:	611a      	strmi	r2, [r3, #16]

        /// Wait for update to complete
        _flash_wait_done();

        // lock OB again.
        SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
 8001b34:	4b1c      	ldr	r3, [pc, #112]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b36:	695a      	ldr	r2, [r3, #20]
 8001b38:	f042 4280 	orr.w	r2, r2, #1073741824	; 0x40000000
 8001b3c:	615a      	str	r2, [r3, #20]

        // include "launch" to make them take effect NOW
        SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
 8001b3e:	695a      	ldr	r2, [r3, #20]
 8001b40:	f042 6200 	orr.w	r2, r2, #134217728	; 0x8000000
 8001b44:	615a      	str	r2, [r3, #20]
 8001b46:	461a      	mov	r2, r3
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
 8001b48:	6911      	ldr	r1, [r2, #16]
 8001b4a:	4b17      	ldr	r3, [pc, #92]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b4c:	03c8      	lsls	r0, r1, #15
 8001b4e:	d4fb      	bmi.n	8001b48 <flash_ob_lock.part.1+0x7c>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
 8001b50:	691a      	ldr	r2, [r3, #16]
 8001b52:	0791      	lsls	r1, r2, #30
 8001b54:	d41e      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
 8001b56:	691a      	ldr	r2, [r3, #16]
 8001b58:	0712      	lsls	r2, r2, #28
 8001b5a:	d41b      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001b5c:	691a      	ldr	r2, [r3, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
 8001b5e:	06d0      	lsls	r0, r2, #27
 8001b60:	d418      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001b62:	691a      	ldr	r2, [r3, #16]
 8001b64:	0691      	lsls	r1, r2, #26
 8001b66:	d415      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001b68:	691a      	ldr	r2, [r3, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
 8001b6a:	0652      	lsls	r2, r2, #25
 8001b6c:	d412      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001b6e:	691a      	ldr	r2, [r3, #16]
 8001b70:	0610      	lsls	r0, r2, #24
 8001b72:	d40f      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b74:	691a      	ldr	r2, [r3, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
 8001b76:	05d1      	lsls	r1, r2, #23
 8001b78:	d40c      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b7a:	691a      	ldr	r2, [r3, #16]
 8001b7c:	0592      	lsls	r2, r2, #22
 8001b7e:	d409      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b80:	691b      	ldr	r3, [r3, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
 8001b82:	0458      	lsls	r0, r3, #17
 8001b84:	d406      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b86:	4b08      	ldr	r3, [pc, #32]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b88:	691a      	ldr	r2, [r3, #16]
 8001b8a:	0411      	lsls	r1, r2, #16
 8001b8c:	d402      	bmi.n	8001b94 <flash_ob_lock.part.1+0xc8>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
 8001b8e:	699a      	ldr	r2, [r3, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
 8001b90:	2a00      	cmp	r2, #0
 8001b92:	da02      	bge.n	8001b9a <flash_ob_lock.part.1+0xce>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
 8001b94:	4b04      	ldr	r3, [pc, #16]	; (8001ba8 <flash_ob_lock.part.1+0xdc>)
 8001b96:	691b      	ldr	r3, [r3, #16]
 8001b98:	4770      	bx	lr
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
 8001b9a:	691a      	ldr	r2, [r3, #16]
 8001b9c:	07d2      	lsls	r2, r2, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
 8001b9e:	bf44      	itt	mi
 8001ba0:	2201      	movmi	r2, #1
 8001ba2:	611a      	strmi	r2, [r3, #16]
 8001ba4:	4770      	bx	lr
 8001ba6:	bf00      	nop
 8001ba8:	40022000 	.word	0x40022000

08001bac <flash_setup0>:

// flash_setup0()
//
    void
flash_setup0(void)
{
 8001bac:	b507      	push	{r0, r1, r2, lr}
    // put the ram-callable functions into place
    extern uint8_t _srelocate, _etext, _erelocate;
    memcpy(&_srelocate, &_etext, ((uint32_t)&_erelocate)-(uint32_t)&_srelocate);
 8001bae:	4809      	ldr	r0, [pc, #36]	; (8001bd4 <flash_setup0+0x28>)
 8001bb0:	4a09      	ldr	r2, [pc, #36]	; (8001bd8 <flash_setup0+0x2c>)
 8001bb2:	490a      	ldr	r1, [pc, #40]	; (8001bdc <flash_setup0+0x30>)
 8001bb4:	1a12      	subs	r2, r2, r0
 8001bb6:	f004 fe77 	bl	80068a8 <memcpy>

    // turn on clock to flash registers
    __HAL_RCC_FLASH_CLK_ENABLE();
 8001bba:	4b09      	ldr	r3, [pc, #36]	; (8001be0 <flash_setup0+0x34>)
 8001bbc:	6c9a      	ldr	r2, [r3, #72]	; 0x48
 8001bbe:	f442 7280 	orr.w	r2, r2, #256	; 0x100
 8001bc2:	649a      	str	r2, [r3, #72]	; 0x48
 8001bc4:	6c9b      	ldr	r3, [r3, #72]	; 0x48
 8001bc6:	f403 7380 	and.w	r3, r3, #256	; 0x100
 8001bca:	9301      	str	r3, [sp, #4]
 8001bcc:	9b01      	ldr	r3, [sp, #4]
}
 8001bce:	b003      	add	sp, #12
 8001bd0:	f85d fb04 	ldr.w	pc, [sp], #4
 8001bd4:	10006000 	.word	0x10006000
 8001bd8:	1000624c 	.word	0x1000624c
 8001bdc:	08007588 	.word	0x08007588
 8001be0:	40021000 	.word	0x40021000

08001be4 <flash_lock>:
//
    void
flash_lock(void)
{
    // see HAL_FLASH_Lock();
    SET_BIT(FLASH->CR, FLASH_CR_LOCK);
 8001be4:	4a02      	ldr	r2, [pc, #8]	; (8001bf0 <flash_lock+0xc>)
 8001be6:	6953      	ldr	r3, [r2, #20]
 8001be8:	f043 4300 	orr.w	r3, r3, #2147483648	; 0x80000000
 8001bec:	6153      	str	r3, [r2, #20]
 8001bee:	4770      	bx	lr
 8001bf0:	40022000 	.word	0x40022000

08001bf4 <flash_unlock>:
//
    void
flash_unlock(void)
{
    // see HAL_FLASH_Unlock();
    if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) {
 8001bf4:	4b07      	ldr	r3, [pc, #28]	; (8001c14 <flash_unlock+0x20>)
 8001bf6:	695a      	ldr	r2, [r3, #20]
 8001bf8:	2a00      	cmp	r2, #0
 8001bfa:	da0a      	bge.n	8001c12 <flash_unlock+0x1e>
        // Authorize the FLASH Registers access
        WRITE_REG(FLASH->KEYR, FLASH_KEY1);
 8001bfc:	4a06      	ldr	r2, [pc, #24]	; (8001c18 <flash_unlock+0x24>)
 8001bfe:	609a      	str	r2, [r3, #8]
        WRITE_REG(FLASH->KEYR, FLASH_KEY2);
 8001c00:	f102 3288 	add.w	r2, r2, #2290649224	; 0x88888888
 8001c04:	609a      	str	r2, [r3, #8]

        if(READ_BIT(FLASH->CR, FLASH_CR_LOCK)) {
 8001c06:	695b      	ldr	r3, [r3, #20]
 8001c08:	2b00      	cmp	r3, #0
 8001c0a:	da02      	bge.n	8001c12 <flash_unlock+0x1e>
            INCONSISTENT("failed to unlock");
 8001c0c:	4803      	ldr	r0, [pc, #12]	; (8001c1c <flash_unlock+0x28>)
 8001c0e:	f7fe bbdd 	b.w	80003cc <fatal_error>
 8001c12:	4770      	bx	lr
 8001c14:	40022000 	.word	0x40022000
 8001c18:	45670123 	.word	0x45670123
 8001c1c:	08007230 	.word	0x08007230

08001c20 <flash_ob_lock>:
// - also does "launch" when done
// - also locks/unlocks the main flash
//
    void
flash_ob_lock(bool lock)
{
 8001c20:	b510      	push	{r4, lr}
    if(!lock) {
 8001c22:	b990      	cbnz	r0, 8001c4a <flash_ob_lock+0x2a>
        // unlock sequence
        if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) {
 8001c24:	4c0b      	ldr	r4, [pc, #44]	; (8001c54 <flash_ob_lock+0x34>)
 8001c26:	6963      	ldr	r3, [r4, #20]
 8001c28:	005a      	lsls	r2, r3, #1
 8001c2a:	d512      	bpl.n	8001c52 <flash_ob_lock+0x32>
            flash_unlock();
 8001c2c:	f7ff ffe2 	bl	8001bf4 <flash_unlock>

            WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
 8001c30:	4b09      	ldr	r3, [pc, #36]	; (8001c58 <flash_ob_lock+0x38>)
 8001c32:	60e3      	str	r3, [r4, #12]
            WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
 8001c34:	f103 3344 	add.w	r3, r3, #1145324612	; 0x44444444
 8001c38:	60e3      	str	r3, [r4, #12]

            if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) {
 8001c3a:	6963      	ldr	r3, [r4, #20]
 8001c3c:	005b      	lsls	r3, r3, #1
 8001c3e:	d508      	bpl.n	8001c52 <flash_ob_lock+0x32>
                INCONSISTENT("failed to OB unlock");
 8001c40:	4806      	ldr	r0, [pc, #24]	; (8001c5c <flash_ob_lock+0x3c>)
        // include "launch" to make them take effect NOW
        SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);

        _flash_wait_done();
    }
}
 8001c42:	e8bd 4010 	ldmia.w	sp!, {r4, lr}

            WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
            WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);

            if(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK)) {
                INCONSISTENT("failed to OB unlock");
 8001c46:	f7fe bbc1 	b.w	80003cc <fatal_error>
        // include "launch" to make them take effect NOW
        SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);

        _flash_wait_done();
    }
}
 8001c4a:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
 8001c4e:	f7ff bf3d 	b.w	8001acc <flash_ob_lock.part.1>
 8001c52:	bd10      	pop	{r4, pc}
 8001c54:	40022000 	.word	0x40022000
 8001c58:	08192a3b 	.word	0x08192a3b
 8001c5c:	08007230 	.word	0x08007230

08001c60 <pick_pairing_secret>:

// pick_pairing_secret()
//
    static void
pick_pairing_secret(void)
{
 8001c60:	b5d0      	push	{r4, r6, r7, lr}
 8001c62:	f5ad 6d84 	sub.w	sp, sp, #1056	; 0x420
    // important the RNG works here. ok to call setup multiple times.
    rng_setup();
 8001c66:	f000 f9b3 	bl	8001fd0 <rng_setup>
 8001c6a:	f44f 747a 	mov.w	r4, #1000	; 0x3e8

    // Demo to anyone watching that the RNG is working, but likely only
    // to be seen by production team during self-test/initial powerup.
    uint8_t    tmp[1024];
    for(int i=0; i<1000; i++) {
        rng_buffer(tmp, sizeof(tmp));
 8001c6e:	f44f 6180 	mov.w	r1, #1024	; 0x400
 8001c72:	a808      	add	r0, sp, #32
 8001c74:	f000 f9d8 	bl	8002028 <rng_buffer>

        oled_show_raw(sizeof(tmp), (void *)tmp);
 8001c78:	a908      	add	r1, sp, #32
 8001c7a:	f44f 6080 	mov.w	r0, #1024	; 0x400
 8001c7e:	f7fe ffb1 	bl	8000be4 <oled_show_raw>
    rng_setup();

    // Demo to anyone watching that the RNG is working, but likely only
    // to be seen by production team during self-test/initial powerup.
    uint8_t    tmp[1024];
    for(int i=0; i<1000; i++) {
 8001c82:	3c01      	subs	r4, #1
 8001c84:	d1f3      	bne.n	8001c6e <pick_pairing_secret+0xe>
    }

    // .. but don't use those numbers, because those are semi-public now.
    uint32_t secret[8];
    for(int i=0; i<8; i++) {
        secret[i] = rng_sample();
 8001c86:	f000 f98f 	bl	8001fa8 <rng_sample>
 8001c8a:	f84d 0024 	str.w	r0, [sp, r4, lsl #2]
        oled_show_raw(sizeof(tmp), (void *)tmp);
    }

    // .. but don't use those numbers, because those are semi-public now.
    uint32_t secret[8];
    for(int i=0; i<8; i++) {
 8001c8e:	3401      	adds	r4, #1
 8001c90:	2c08      	cmp	r4, #8
 8001c92:	d1f8      	bne.n	8001c86 <pick_pairing_secret+0x26>
        secret[i] = rng_sample();
    }

    // enforce policy that first word is not all ones (so it never
    // looks like unprogrammed flash).
    while(secret[0] == ~0) {
 8001c94:	9b00      	ldr	r3, [sp, #0]
 8001c96:	3301      	adds	r3, #1
 8001c98:	d103      	bne.n	8001ca2 <pick_pairing_secret+0x42>
        secret[0] = rng_sample();
 8001c9a:	f000 f985 	bl	8001fa8 <rng_sample>
 8001c9e:	9000      	str	r0, [sp, #0]
 8001ca0:	e7f8      	b.n	8001c94 <pick_pairing_secret+0x34>


    // write into flash here
    uint32_t dest = (uint32_t)&rom_secrets->pairing_secret;

    flash_unlock();
 8001ca2:	f7ff ffa7 	bl	8001bf4 <flash_unlock>
 8001ca6:	2400      	movs	r4, #0
    for(int i=0; i<8; i+=2, dest += 8) {
        uint64_t    val = (((uint64_t)secret[i]) << 32) | secret[i+1];
 8001ca8:	eb0d 0304 	add.w	r3, sp, r4

        if(flash_burn(dest, val)) {
 8001cac:	f85d 7004 	ldr.w	r7, [sp, r4]
 8001cb0:	685a      	ldr	r2, [r3, #4]
 8001cb2:	2600      	movs	r6, #0
 8001cb4:	4630      	mov	r0, r6
 8001cb6:	4639      	mov	r1, r7
 8001cb8:	ea40 0002 	orr.w	r0, r0, r2
 8001cbc:	4602      	mov	r2, r0
 8001cbe:	f104 6000 	add.w	r0, r4, #134217728	; 0x8000000
 8001cc2:	460b      	mov	r3, r1
 8001cc4:	f500 40f0 	add.w	r0, r0, #30720	; 0x7800
 8001cc8:	f004 fe3a 	bl	8006940 <__flash_burn_veneer>
 8001ccc:	b110      	cbz	r0, 8001cd4 <pick_pairing_secret+0x74>
            INCONSISTENT("flash fail");
 8001cce:	4805      	ldr	r0, [pc, #20]	; (8001ce4 <pick_pairing_secret+0x84>)
 8001cd0:	f7fe fb7c 	bl	80003cc <fatal_error>
 8001cd4:	3408      	adds	r4, #8

    // write into flash here
    uint32_t dest = (uint32_t)&rom_secrets->pairing_secret;

    flash_unlock();
    for(int i=0; i<8; i+=2, dest += 8) {
 8001cd6:	2c20      	cmp	r4, #32
 8001cd8:	d1e6      	bne.n	8001ca8 <pick_pairing_secret+0x48>

        if(flash_burn(dest, val)) {
            INCONSISTENT("flash fail");
        }
    }
    flash_lock();
 8001cda:	f7ff ff83 	bl	8001be4 <flash_lock>
}
 8001cde:	f50d 6d84 	add.w	sp, sp, #1056	; 0x420
 8001ce2:	bdd0      	pop	{r4, r6, r7, pc}
 8001ce4:	08007230 	.word	0x08007230

08001ce8 <flash_save_ae_serial>:
//
// Write the serial number of ATECC508A into flash forever.
//
    void
flash_save_ae_serial(const uint8_t serial[9])
{
 8001ce8:	b51f      	push	{r0, r1, r2, r3, r4, lr}
 8001cea:	4604      	mov	r4, r0

    uint64_t    tmp[2];
    memset(&tmp, 0x0, sizeof(tmp));
 8001cec:	2210      	movs	r2, #16
 8001cee:	2100      	movs	r1, #0
 8001cf0:	4668      	mov	r0, sp
 8001cf2:	f004 fdff 	bl	80068f4 <memset>
    memcpy(&tmp, serial, 9);
 8001cf6:	6820      	ldr	r0, [r4, #0]
 8001cf8:	6861      	ldr	r1, [r4, #4]
 8001cfa:	7a22      	ldrb	r2, [r4, #8]
 8001cfc:	466b      	mov	r3, sp
 8001cfe:	c303      	stmia	r3!, {r0, r1}
 8001d00:	701a      	strb	r2, [r3, #0]

    flash_setup0();
 8001d02:	f7ff ff53 	bl	8001bac <flash_setup0>
    flash_unlock();
 8001d06:	f7ff ff75 	bl	8001bf4 <flash_unlock>

    if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[0], tmp[0])) {
 8001d0a:	e9dd 2300 	ldrd	r2, r3, [sp]
 8001d0e:	480a      	ldr	r0, [pc, #40]	; (8001d38 <flash_save_ae_serial+0x50>)
 8001d10:	f004 fe16 	bl	8006940 <__flash_burn_veneer>
 8001d14:	b110      	cbz	r0, 8001d1c <flash_save_ae_serial+0x34>
        INCONSISTENT("fail1");
 8001d16:	4809      	ldr	r0, [pc, #36]	; (8001d3c <flash_save_ae_serial+0x54>)
 8001d18:	f7fe fb58 	bl	80003cc <fatal_error>
    }
    if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[1], tmp[1])) {
 8001d1c:	e9dd 2302 	ldrd	r2, r3, [sp, #8]
 8001d20:	4807      	ldr	r0, [pc, #28]	; (8001d40 <flash_save_ae_serial+0x58>)
 8001d22:	f004 fe0d 	bl	8006940 <__flash_burn_veneer>
 8001d26:	b110      	cbz	r0, 8001d2e <flash_save_ae_serial+0x46>
        INCONSISTENT("fail2");
 8001d28:	4804      	ldr	r0, [pc, #16]	; (8001d3c <flash_save_ae_serial+0x54>)
 8001d2a:	f7fe fb4f 	bl	80003cc <fatal_error>
    }

    flash_lock();
}
 8001d2e:	b004      	add	sp, #16
 8001d30:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
    }
    if(flash_burn((uint32_t)&rom_secrets->ae_serial_number[1], tmp[1])) {
        INCONSISTENT("fail2");
    }

    flash_lock();
 8001d34:	f7ff bf56 	b.w	8001be4 <flash_lock>
 8001d38:	08007840 	.word	0x08007840
 8001d3c:	08007230 	.word	0x08007230
 8001d40:	08007848 	.word	0x08007848

08001d44 <flash_save_bag_number>:
//
// Write bag number (probably a string)
//
    void
flash_save_bag_number(const uint8_t new_number[32])
{
 8001d44:	b570      	push	{r4, r5, r6, lr}
 8001d46:	4605      	mov	r5, r0

    uint32_t dest = (uint32_t)&rom_secrets->bag_number[0];
    uint64_t *src = (uint64_t *)new_number;

    flash_setup0();
 8001d48:	f7ff ff30 	bl	8001bac <flash_setup0>
    flash_unlock();
 8001d4c:	f7ff ff52 	bl	8001bf4 <flash_unlock>
//
    void
flash_save_bag_number(const uint8_t new_number[32])
{

    uint32_t dest = (uint32_t)&rom_secrets->bag_number[0];
 8001d50:	4c09      	ldr	r4, [pc, #36]	; (8001d78 <flash_save_bag_number+0x34>)
    flash_setup0();
    flash_unlock();

    // NOTE: can only write once! No provision for read/check, and write
    // when non-ones will fail.
    for(int i=0; i<(32/8); i++, dest+=8, src++) {
 8001d52:	4e0a      	ldr	r6, [pc, #40]	; (8001d7c <flash_save_bag_number+0x38>)
 8001d54:	3d08      	subs	r5, #8
        if(flash_burn(dest, *src)) {
 8001d56:	e9f5 2302 	ldrd	r2, r3, [r5, #8]!
 8001d5a:	4620      	mov	r0, r4
 8001d5c:	f004 fdf0 	bl	8006940 <__flash_burn_veneer>
 8001d60:	b110      	cbz	r0, 8001d68 <flash_save_bag_number+0x24>
            INCONSISTENT("fail write");
 8001d62:	4807      	ldr	r0, [pc, #28]	; (8001d80 <flash_save_bag_number+0x3c>)
 8001d64:	f7fe fb32 	bl	80003cc <fatal_error>
    flash_setup0();
    flash_unlock();

    // NOTE: can only write once! No provision for read/check, and write
    // when non-ones will fail.
    for(int i=0; i<(32/8); i++, dest+=8, src++) {
 8001d68:	3408      	adds	r4, #8
 8001d6a:	42b4      	cmp	r4, r6
 8001d6c:	d1f3      	bne.n	8001d56 <flash_save_bag_number+0x12>
            INCONSISTENT("fail write");
        }
    }

    flash_lock();
}
 8001d6e:	e8bd 4070 	ldmia.w	sp!, {r4, r5, r6, lr}
        if(flash_burn(dest, *src)) {
            INCONSISTENT("fail write");
        }
    }

    flash_lock();
 8001d72:	f7ff bf37 	b.w	8001be4 <flash_lock>
 8001d76:	bf00      	nop
 8001d78:	08007850 	.word	0x08007850
 8001d7c:	08007870 	.word	0x08007870
 8001d80:	08007230 	.word	0x08007230

08001d84 <flash_setup>:
//
// This is really a state-machine, to recover boards that are booted w/ missing AE chip.
//
    void
flash_setup(void)
{
 8001d84:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
    flash_setup0();

    // see if we have picked a pairing secret yet.
    bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
 8001d88:	4d2e      	ldr	r5, [pc, #184]	; (8001e44 <flash_setup+0xc0>)
//
// This is really a state-machine, to recover boards that are booted w/ missing AE chip.
//
    void
flash_setup(void)
{
 8001d8a:	b088      	sub	sp, #32
    flash_setup0();
 8001d8c:	f7ff ff0e 	bl	8001bac <flash_setup0>

    // see if we have picked a pairing secret yet.
    bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
 8001d90:	2120      	movs	r1, #32
 8001d92:	4628      	mov	r0, r5
 8001d94:	f000 f8e0 	bl	8001f58 <check_all_ones>
    bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
 8001d98:	2120      	movs	r1, #32
flash_setup(void)
{
    flash_setup0();

    // see if we have picked a pairing secret yet.
    bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
 8001d9a:	4680      	mov	r8, r0
    bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
 8001d9c:	482a      	ldr	r0, [pc, #168]	; (8001e48 <flash_setup+0xc4>)
 8001d9e:	f000 f8db 	bl	8001f58 <check_all_ones>
    bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0);
 8001da2:	e9d5 6710 	ldrd	r6, r7, [r5, #64]	; 0x40
{
    flash_setup0();

    // see if we have picked a pairing secret yet.
    bool blank_ps = check_all_ones(rom_secrets->pairing_secret, 32);
    bool blank_xor = check_all_ones(rom_secrets->pairing_secret_xor, 32);
 8001da6:	4604      	mov	r4, r0
    bool blank_ae = (~rom_secrets->ae_serial_number[0] == 0);

    if(blank_ps) {
 8001da8:	f1b8 0f00 	cmp.w	r8, #0
 8001dac:	d001      	beq.n	8001db2 <flash_setup+0x2e>
        // get some good entropy, save it.
        pick_pairing_secret();
 8001dae:	f7ff ff57 	bl	8001c60 <pick_pairing_secret>

        blank_ps = false;
    }

    if(blank_xor || blank_ae) {
 8001db2:	b924      	cbnz	r4, 8001dbe <flash_setup+0x3a>
 8001db4:	3701      	adds	r7, #1
 8001db6:	bf08      	it	eq
 8001db8:	f1b6 3fff 	cmpeq.w	r6, #4294967295	; 0xffffffff
 8001dbc:	d121      	bne.n	8001e02 <flash_setup+0x7e>

        // configure and lock-down the ATECC508A
        int rv = ae_setup_config();
 8001dbe:	f001 f82d 	bl	8002e1c <ae_setup_config>

        if(rv) {
 8001dc2:	b120      	cbz	r0, 8001dce <flash_setup+0x4a>
            // hardware fail speaking to AE chip ... be careful not to brick,
            // Do not continue!! We might fix the board, or add missing pullup, etc.
            oled_show(screen_brick);
 8001dc4:	4821      	ldr	r0, [pc, #132]	; (8001e4c <flash_setup+0xc8>)
 8001dc6:	f7fe ff37 	bl	8000c38 <oled_show>
 8001dca:	bf30      	wfi
 8001dcc:	e7fd      	b.n	8001dca <flash_setup+0x46>
            LOCKUP_FOREVER();
        }

        if(blank_xor) {
 8001dce:	b19c      	cbz	r4, 8001df8 <flash_setup+0x74>
    // BUT: we are using to mark the 2nd half of a two-phase commit w.r.t AE setup

    uint64_t *src = (uint64_t *)&rom_secrets->pairing_secret;
    uint32_t dest = (uint32_t)&rom_secrets->pairing_secret_xor;

    flash_unlock();
 8001dd0:	f7ff ff10 	bl	8001bf4 <flash_unlock>
 8001dd4:	4c1e      	ldr	r4, [pc, #120]	; (8001e50 <flash_setup+0xcc>)
    for(int i=0; i<(32/8); i++, dest+=8, src++) {
 8001dd6:	4d1f      	ldr	r5, [pc, #124]	; (8001e54 <flash_setup+0xd0>)
 8001dd8:	f104 0028 	add.w	r0, r4, #40	; 0x28
        uint64_t    val = ~(*src);

        if(flash_burn(dest, val)) {
 8001ddc:	e9f4 2302 	ldrd	r2, r3, [r4, #8]!
 8001de0:	43d2      	mvns	r2, r2
 8001de2:	43db      	mvns	r3, r3
 8001de4:	f004 fdac 	bl	8006940 <__flash_burn_veneer>
 8001de8:	b110      	cbz	r0, 8001df0 <flash_setup+0x6c>
            INCONSISTENT("flash xor fail");
 8001dea:	481b      	ldr	r0, [pc, #108]	; (8001e58 <flash_setup+0xd4>)
 8001dec:	f7fe faee 	bl	80003cc <fatal_error>

    uint64_t *src = (uint64_t *)&rom_secrets->pairing_secret;
    uint32_t dest = (uint32_t)&rom_secrets->pairing_secret_xor;

    flash_unlock();
    for(int i=0; i<(32/8); i++, dest+=8, src++) {
 8001df0:	42ac      	cmp	r4, r5
 8001df2:	d1f1      	bne.n	8001dd8 <flash_setup+0x54>

        if(flash_burn(dest, val)) {
            INCONSISTENT("flash xor fail");
        }
    }
    flash_lock();
 8001df4:	f7ff fef6 	bl	8001be4 <flash_lock>
            // write secret again, complemented, to indicate successful AE programming
            confirm_pairing_secret();
        }

        // real power cycle required now.
        oled_show(screen_replug);
 8001df8:	4818      	ldr	r0, [pc, #96]	; (8001e5c <flash_setup+0xd8>)
 8001dfa:	f7fe ff1d 	bl	8000c38 <oled_show>
 8001dfe:	bf30      	wfi
 8001e00:	e7fd      	b.n	8001dfe <flash_setup+0x7a>
    }

    if(!blank_ps && !blank_xor) {
        // check the XOR value also written: 2 phase commit
        uint8_t tmp[32];
        memcpy(tmp, rom_secrets->pairing_secret, 32);
 8001e02:	4d10      	ldr	r5, [pc, #64]	; (8001e44 <flash_setup+0xc0>)
 8001e04:	cd0f      	ldmia	r5!, {r0, r1, r2, r3}
 8001e06:	466c      	mov	r4, sp
 8001e08:	c40f      	stmia	r4!, {r0, r1, r2, r3}
 8001e0a:	e895 000f 	ldmia.w	r5, {r0, r1, r2, r3}
 8001e0e:	e884 000f 	stmia.w	r4, {r0, r1, r2, r3}
 8001e12:	4a13      	ldr	r2, [pc, #76]	; (8001e60 <flash_setup+0xdc>)
bool check_equal(const void *aV, const void *bV, int len);

// XOR-mixin more bytes; acc = acc XOR more for each byte
void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
{
	for(; len; len--, more++, acc++) {
 8001e14:	4c13      	ldr	r4, [pc, #76]	; (8001e64 <flash_setup+0xe0>)
 8001e16:	466b      	mov	r3, sp
 8001e18:	4668      	mov	r0, sp
		*(acc) ^= *(more);
 8001e1a:	f812 1f01 	ldrb.w	r1, [r2, #1]!
 8001e1e:	781d      	ldrb	r5, [r3, #0]
bool check_equal(const void *aV, const void *bV, int len);

// XOR-mixin more bytes; acc = acc XOR more for each byte
void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
{
	for(; len; len--, more++, acc++) {
 8001e20:	42a2      	cmp	r2, r4
		*(acc) ^= *(more);
 8001e22:	ea81 0105 	eor.w	r1, r1, r5
 8001e26:	f803 1b01 	strb.w	r1, [r3], #1
bool check_equal(const void *aV, const void *bV, int len);

// XOR-mixin more bytes; acc = acc XOR more for each byte
void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
{
	for(; len; len--, more++, acc++) {
 8001e2a:	d1f6      	bne.n	8001e1a <flash_setup+0x96>
        xor_mixin(tmp, rom_secrets->pairing_secret_xor, 32);

        if(!check_all_ones(tmp, 32)) {
 8001e2c:	2120      	movs	r1, #32
 8001e2e:	f000 f893 	bl	8001f58 <check_all_ones>
 8001e32:	b920      	cbnz	r0, 8001e3e <flash_setup+0xba>
            oled_show(screen_corrupt);
 8001e34:	480c      	ldr	r0, [pc, #48]	; (8001e68 <flash_setup+0xe4>)
 8001e36:	f7fe feff 	bl	8000c38 <oled_show>
 8001e3a:	bf30      	wfi
 8001e3c:	e7fd      	b.n	8001e3a <flash_setup+0xb6>
    // That's fine if we intend to ship units locked already.
    
    // Do NOT do write every boot, as it might wear-out
    // the flash bits in OB.

}
 8001e3e:	b008      	add	sp, #32
 8001e40:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 8001e44:	08007800 	.word	0x08007800
 8001e48:	08007820 	.word	0x08007820
 8001e4c:	08006d5b 	.word	0x08006d5b
 8001e50:	080077f8 	.word	0x080077f8
 8001e54:	08007818 	.word	0x08007818
 8001e58:	08007230 	.word	0x08007230
 8001e5c:	08006cfa 	.word	0x08006cfa
 8001e60:	0800781f 	.word	0x0800781f
 8001e64:	0800783f 	.word	0x0800783f
 8001e68:	08006ff1 	.word	0x08006ff1

08001e6c <flash_lockdown_hard>:
// 
// This is a one-way trip. Might need power cycle to (fully?) take effect.
//
    void
flash_lockdown_hard(uint8_t rdp_level_code)
{
 8001e6c:	b510      	push	{r4, lr}
 8001e6e:	4604      	mov	r4, r0
    flash_setup0();
 8001e70:	f7ff fe9c 	bl	8001bac <flash_setup0>

    // see FLASH_OB_WRPConfig()

    flash_ob_lock(false);
 8001e74:	2000      	movs	r0, #0
 8001e76:	f7ff fed3 	bl	8001c20 <flash_ob_lock>
        // lock first 32k against any writes
        FLASH->WRP1AR = (num_pages_locked << 16);
 8001e7a:	4b07      	ldr	r3, [pc, #28]	; (8001e98 <flash_lockdown_hard+0x2c>)
 8001e7c:	f44f 2270 	mov.w	r2, #983040	; 0xf0000
 8001e80:	62da      	str	r2, [r3, #44]	; 0x2c
        FLASH->WRP1BR = 0xff;      // unused.
 8001e82:	22ff      	movs	r2, #255	; 0xff
 8001e84:	631a      	str	r2, [r3, #48]	; 0x30
        FLASH->WRP2AR = 0xff;      // unused.
 8001e86:	64da      	str	r2, [r3, #76]	; 0x4c
        FLASH->WRP2BR = 0xff;      // unused.
 8001e88:	651a      	str	r2, [r3, #80]	; 0x50
        FLASH->PCROP2ER = (1<<31);      // set PCROP_RDP bit, since maybe we need to?
        FLASH->PCROP2SR = 0xffff;
#endif

        // set protection level
        FLASH->OPTR = 0xffeff800 | rdp_level_code;    // select level X, other values as observed
 8001e8a:	4a04      	ldr	r2, [pc, #16]	; (8001e9c <flash_lockdown_hard+0x30>)
 8001e8c:	4322      	orrs	r2, r4
 8001e8e:	621a      	str	r2, [r3, #32]

    flash_ob_lock(true);
}
 8001e90:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
 8001e94:	f7ff be1a 	b.w	8001acc <flash_ob_lock.part.1>
 8001e98:	40022000 	.word	0x40022000
 8001e9c:	ffeff800 	.word	0xffeff800

08001ea0 <backup_data_get>:
// backup_data_get()
//
    uint32_t
backup_data_get(int idx)
{
    ASSERT(idx < 32);
 8001ea0:	281f      	cmp	r0, #31

// backup_data_get()
//
    uint32_t
backup_data_get(int idx)
{
 8001ea2:	b510      	push	{r4, lr}
 8001ea4:	4604      	mov	r4, r0
    ASSERT(idx < 32);
 8001ea6:	dd02      	ble.n	8001eae <backup_data_get+0xe>
 8001ea8:	4803      	ldr	r0, [pc, #12]	; (8001eb8 <backup_data_get+0x18>)
 8001eaa:	f7fe fa8f 	bl	80003cc <fatal_error>

    return (&RTC->BKP0R)[idx];
 8001eae:	4b03      	ldr	r3, [pc, #12]	; (8001ebc <backup_data_get+0x1c>)
 8001eb0:	f853 0024 	ldr.w	r0, [r3, r4, lsl #2]
}
 8001eb4:	bd10      	pop	{r4, pc}
 8001eb6:	bf00      	nop
 8001eb8:	08006960 	.word	0x08006960
 8001ebc:	40002850 	.word	0x40002850

08001ec0 <backup_data_set>:
// backup_data_set()
//
    void
backup_data_set(int idx, uint32_t new_value)
{
    ASSERT(idx < 32);
 8001ec0:	281f      	cmp	r0, #31

// backup_data_set()
//
    void
backup_data_set(int idx, uint32_t new_value)
{
 8001ec2:	b538      	push	{r3, r4, r5, lr}
 8001ec4:	4604      	mov	r4, r0
 8001ec6:	460d      	mov	r5, r1
    ASSERT(idx < 32);
 8001ec8:	dd02      	ble.n	8001ed0 <backup_data_set+0x10>
 8001eca:	4807      	ldr	r0, [pc, #28]	; (8001ee8 <backup_data_set+0x28>)
 8001ecc:	f7fe fa7e 	bl	80003cc <fatal_error>

    // unlock sequence.
    RTC->WPR = 0xCA;
 8001ed0:	4b06      	ldr	r3, [pc, #24]	; (8001eec <backup_data_set+0x2c>)
 8001ed2:	22ca      	movs	r2, #202	; 0xca
 8001ed4:	625a      	str	r2, [r3, #36]	; 0x24
    RTC->WPR = 0x53;
 8001ed6:	2253      	movs	r2, #83	; 0x53
 8001ed8:	625a      	str	r2, [r3, #36]	; 0x24

    (&RTC->BKP0R)[idx] = new_value;
 8001eda:	4a05      	ldr	r2, [pc, #20]	; (8001ef0 <backup_data_set+0x30>)
 8001edc:	f842 5024 	str.w	r5, [r2, r4, lsl #2]

    // relock (any value)
    // doesn't seem to work tho? stays unlocked
    RTC->WPR = 0xff;
 8001ee0:	22ff      	movs	r2, #255	; 0xff
 8001ee2:	625a      	str	r2, [r3, #36]	; 0x24
 8001ee4:	bd38      	pop	{r3, r4, r5, pc}
 8001ee6:	bf00      	nop
 8001ee8:	08006960 	.word	0x08006960
 8001eec:	40002800 	.word	0x40002800
 8001ef0:	40002850 	.word	0x40002850

08001ef4 <record_highwater_version>:

// record_highwater_version()
//
    int
record_highwater_version(const uint8_t timestamp[8])
{
 8001ef4:	b573      	push	{r0, r1, r4, r5, r6, lr}
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    ASSERT(timestamp[0] < 0x40);
 8001ef6:	7803      	ldrb	r3, [r0, #0]
 8001ef8:	2b3f      	cmp	r3, #63	; 0x3f

// record_highwater_version()
//
    int
record_highwater_version(const uint8_t timestamp[8])
{
 8001efa:	4605      	mov	r5, r0
    const uint8_t *otp = (const uint8_t *)OPT_FLASH_BASE;

    ASSERT(timestamp[0] < 0x40);
 8001efc:	d902      	bls.n	8001f04 <record_highwater_version+0x10>
 8001efe:	4813      	ldr	r0, [pc, #76]	; (8001f4c <record_highwater_version+0x58>)
 8001f00:	f7fe fa64 	bl	80003cc <fatal_error>
    ASSERT(timestamp[0] >= 0x10);
 8001f04:	782b      	ldrb	r3, [r5, #0]
 8001f06:	2b0f      	cmp	r3, #15
 8001f08:	d802      	bhi.n	8001f10 <record_highwater_version+0x1c>
 8001f0a:	4810      	ldr	r0, [pc, #64]	; (8001f4c <record_highwater_version+0x58>)
 8001f0c:	f7fe fa5e 	bl	80003cc <fatal_error>

// record_highwater_version()
//
    int
record_highwater_version(const uint8_t timestamp[8])
{
 8001f10:	4c0f      	ldr	r4, [pc, #60]	; (8001f50 <record_highwater_version+0x5c>)

    ASSERT(timestamp[0] < 0x40);
    ASSERT(timestamp[0] >= 0x10);

    // just write to first blank slot we can find.
    for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
 8001f12:	4e10      	ldr	r6, [pc, #64]	; (8001f54 <record_highwater_version+0x60>)
        if(check_all_ones(otp, 8)) {
 8001f14:	2108      	movs	r1, #8
 8001f16:	4620      	mov	r0, r4
 8001f18:	f000 f81e 	bl	8001f58 <check_all_ones>
 8001f1c:	b180      	cbz	r0, 8001f40 <record_highwater_version+0x4c>
            // here.
            uint64_t val = 0;
            memcpy(&val, timestamp, 8);
 8001f1e:	6869      	ldr	r1, [r5, #4]
 8001f20:	6828      	ldr	r0, [r5, #0]
 8001f22:	466b      	mov	r3, sp
 8001f24:	c303      	stmia	r3!, {r0, r1}

            flash_setup0();
 8001f26:	f7ff fe41 	bl	8001bac <flash_setup0>

            flash_unlock();
 8001f2a:	f7ff fe63 	bl	8001bf4 <flash_unlock>
                flash_burn((uint32_t)otp, val);
 8001f2e:	e9dd 2300 	ldrd	r2, r3, [sp]
 8001f32:	4620      	mov	r0, r4
 8001f34:	f004 fd04 	bl	8006940 <__flash_burn_veneer>
            flash_lock();
 8001f38:	f7ff fe54 	bl	8001be4 <flash_lock>

            return 0;
 8001f3c:	2000      	movs	r0, #0
 8001f3e:	e003      	b.n	8001f48 <record_highwater_version+0x54>

    ASSERT(timestamp[0] < 0x40);
    ASSERT(timestamp[0] >= 0x10);

    // just write to first blank slot we can find.
    for(int i=0; i<NUM_OPT_SLOTS; i++, otp+=8) {
 8001f40:	3408      	adds	r4, #8
 8001f42:	42b4      	cmp	r4, r6
 8001f44:	d1e6      	bne.n	8001f14 <record_highwater_version+0x20>
            return 0;
        }
    }

    // no space.
    return 1;
 8001f46:	2001      	movs	r0, #1
}
 8001f48:	b002      	add	sp, #8
 8001f4a:	bd70      	pop	{r4, r5, r6, pc}
 8001f4c:	08006960 	.word	0x08006960
 8001f50:	1fff7000 	.word	0x1fff7000
 8001f54:	1fff7400 	.word	0x1fff7400

08001f58 <check_all_ones>:
//
// Return T if all bytes are 0xFF
//
	bool
check_all_ones(const void *ptrV, int len)
{
 8001f58:	4401      	add	r1, r0
	uint8_t rv = 0xff;
 8001f5a:	23ff      	movs	r3, #255	; 0xff
	const uint8_t *ptr = (const uint8_t *)ptrV;

	for(; len; len--, ptr++) {
 8001f5c:	4288      	cmp	r0, r1
 8001f5e:	d003      	beq.n	8001f68 <check_all_ones+0x10>
		rv &= *ptr;
 8001f60:	f810 2b01 	ldrb.w	r2, [r0], #1
 8001f64:	4013      	ands	r3, r2
 8001f66:	e7f9      	b.n	8001f5c <check_all_ones+0x4>
	}

	return (rv == 0xff);
}
 8001f68:	3bff      	subs	r3, #255	; 0xff
 8001f6a:	4258      	negs	r0, r3
 8001f6c:	4158      	adcs	r0, r3
 8001f6e:	4770      	bx	lr

08001f70 <check_all_zeros>:
//
// Return T if all bytes are 0x00
//
	bool
check_all_zeros(const void *ptrV, int len)
{
 8001f70:	4401      	add	r1, r0
	uint8_t rv = 0x0;
 8001f72:	2300      	movs	r3, #0
	const uint8_t *ptr = (const uint8_t *)ptrV;

	for(; len; len--, ptr++) {
 8001f74:	4288      	cmp	r0, r1
 8001f76:	d003      	beq.n	8001f80 <check_all_zeros+0x10>
		rv |= *ptr;
 8001f78:	f810 2b01 	ldrb.w	r2, [r0], #1
 8001f7c:	4313      	orrs	r3, r2
 8001f7e:	e7f9      	b.n	8001f74 <check_all_zeros+0x4>
	}

	return (rv == 0x00);
}
 8001f80:	fab3 f083 	clz	r0, r3
 8001f84:	0940      	lsrs	r0, r0, #5
 8001f86:	4770      	bx	lr

08001f88 <check_equal>:
	const uint8_t *left = (const uint8_t *)aV;
	const uint8_t *right = (const uint8_t *)bV;
    uint8_t diff = 0;
    int i;

    for (i = 0; i < len; i++) {
 8001f88:	2300      	movs	r3, #0
//
// Equality check.
//
	bool
check_equal(const void *aV, const void *bV, int len)
{
 8001f8a:	b570      	push	{r4, r5, r6, lr}
	const uint8_t *left = (const uint8_t *)aV;
	const uint8_t *right = (const uint8_t *)bV;
    uint8_t diff = 0;
 8001f8c:	461c      	mov	r4, r3
    int i;

    for (i = 0; i < len; i++) {
 8001f8e:	4293      	cmp	r3, r2
 8001f90:	da05      	bge.n	8001f9e <check_equal+0x16>
        diff |= (left[i] ^ right[i]);
 8001f92:	5cc6      	ldrb	r6, [r0, r3]
 8001f94:	5ccd      	ldrb	r5, [r1, r3]
 8001f96:	4075      	eors	r5, r6
 8001f98:	432c      	orrs	r4, r5
	const uint8_t *left = (const uint8_t *)aV;
	const uint8_t *right = (const uint8_t *)bV;
    uint8_t diff = 0;
    int i;

    for (i = 0; i < len; i++) {
 8001f9a:	3301      	adds	r3, #1
 8001f9c:	e7f7      	b.n	8001f8e <check_equal+0x6>
        diff |= (left[i] ^ right[i]);
    }

    return (diff == 0);
}
 8001f9e:	fab4 f084 	clz	r0, r4
 8001fa2:	0940      	lsrs	r0, r0, #5
 8001fa4:	bd70      	pop	{r4, r5, r6, pc}
	...

08001fa8 <rng_sample>:
        }

        // Get the new number
        uint32_t rv = RNG->DR;

        if(rv != last_rng_result && rv) {
 8001fa8:	4b07      	ldr	r3, [pc, #28]	; (8001fc8 <rng_sample+0x20>)
{
    static uint32_t last_rng_result;

    while(1) {
        /* Check if data register contains valid random data */
        while(!(RNG->SR & RNG_FLAG_DRDY)) {
 8001faa:	4a08      	ldr	r2, [pc, #32]	; (8001fcc <rng_sample+0x24>)
        }

        // Get the new number
        uint32_t rv = RNG->DR;

        if(rv != last_rng_result && rv) {
 8001fac:	6819      	ldr	r1, [r3, #0]

// rng_sample()
//
    uint32_t
rng_sample(void)
{
 8001fae:	b510      	push	{r4, lr}
    static uint32_t last_rng_result;

    while(1) {
        /* Check if data register contains valid random data */
        while(!(RNG->SR & RNG_FLAG_DRDY)) {
 8001fb0:	4614      	mov	r4, r2
 8001fb2:	6850      	ldr	r0, [r2, #4]
 8001fb4:	07c0      	lsls	r0, r0, #31
 8001fb6:	d5fc      	bpl.n	8001fb2 <rng_sample+0xa>
            // busy wait; okay to get stuck here... better than failing.
        }

        // Get the new number
        uint32_t rv = RNG->DR;
 8001fb8:	68a0      	ldr	r0, [r4, #8]

        if(rv != last_rng_result && rv) {
 8001fba:	4288      	cmp	r0, r1
 8001fbc:	d0f9      	beq.n	8001fb2 <rng_sample+0xa>
 8001fbe:	2800      	cmp	r0, #0
 8001fc0:	d0f7      	beq.n	8001fb2 <rng_sample+0xa>
            last_rng_result = rv;
 8001fc2:	6018      	str	r0, [r3, #0]

        // keep trying if not a new number
    }

    // NOT-REACHED
}
 8001fc4:	bd10      	pop	{r4, pc}
 8001fc6:	bf00      	nop
 8001fc8:	100062b4 	.word	0x100062b4
 8001fcc:	50060800 	.word	0x50060800

08001fd0 <rng_setup>:
// rng_setup()
//
    void
rng_setup(void)
{
    if(RNG->CR & RNG_CR_RNGEN) {
 8001fd0:	4b12      	ldr	r3, [pc, #72]	; (800201c <rng_setup+0x4c>)
 8001fd2:	681a      	ldr	r2, [r3, #0]
 8001fd4:	0752      	lsls	r2, r2, #29

// rng_setup()
//
    void
rng_setup(void)
{
 8001fd6:	b513      	push	{r0, r1, r4, lr}
    if(RNG->CR & RNG_CR_RNGEN) {
 8001fd8:	d41e      	bmi.n	8002018 <rng_setup+0x48>
        // already setup
        return;
    }

    // Enable the Peripheral
    __HAL_RCC_RNG_CLK_ENABLE();
 8001fda:	4a11      	ldr	r2, [pc, #68]	; (8002020 <rng_setup+0x50>)
 8001fdc:	6cd1      	ldr	r1, [r2, #76]	; 0x4c
 8001fde:	f441 2180 	orr.w	r1, r1, #262144	; 0x40000
 8001fe2:	64d1      	str	r1, [r2, #76]	; 0x4c
 8001fe4:	6cd2      	ldr	r2, [r2, #76]	; 0x4c
 8001fe6:	f402 2280 	and.w	r2, r2, #262144	; 0x40000
 8001fea:	9201      	str	r2, [sp, #4]
 8001fec:	9a01      	ldr	r2, [sp, #4]

    // Turn on feature.
    RNG->CR |=  RNG_CR_RNGEN;
 8001fee:	681a      	ldr	r2, [r3, #0]
 8001ff0:	f042 0204 	orr.w	r2, r2, #4
 8001ff4:	601a      	str	r2, [r3, #0]

    // Sample twice to be sure that we have a 
    // valid RNG result.
    uint32_t chk = rng_sample();
 8001ff6:	f7ff ffd7 	bl	8001fa8 <rng_sample>
 8001ffa:	4604      	mov	r4, r0
    uint32_t chk2 = rng_sample();
 8001ffc:	f7ff ffd4 	bl	8001fa8 <rng_sample>

    // die if we are clearly not getting random values
    if(chk == 0 || chk == ~0
 8002000:	1e63      	subs	r3, r4, #1
 8002002:	3303      	adds	r3, #3
 8002004:	d804      	bhi.n	8002010 <rng_setup+0x40>
        || chk2 == 0 || chk2 == ~0
 8002006:	1e43      	subs	r3, r0, #1
 8002008:	3303      	adds	r3, #3
 800200a:	d801      	bhi.n	8002010 <rng_setup+0x40>
        || chk == chk2
 800200c:	4284      	cmp	r4, r0
 800200e:	d103      	bne.n	8002018 <rng_setup+0x48>
    ) {
        INCONSISTENT("bad rng");
 8002010:	4804      	ldr	r0, [pc, #16]	; (8002024 <rng_setup+0x54>)
 8002012:	f7fe f9db 	bl	80003cc <fatal_error>
 8002016:	e7fe      	b.n	8002016 <rng_setup+0x46>

        while(1) ;
    }
}
 8002018:	b002      	add	sp, #8
 800201a:	bd10      	pop	{r4, pc}
 800201c:	50060800 	.word	0x50060800
 8002020:	40021000 	.word	0x40021000
 8002024:	08007230 	.word	0x08007230

08002028 <rng_buffer>:

// rng_buffer()
//
    void
rng_buffer(uint8_t *result, int len)
{
 8002028:	b5f7      	push	{r0, r1, r2, r4, r5, r6, r7, lr}
 800202a:	4607      	mov	r7, r0
 800202c:	460e      	mov	r6, r1
    while(len > 0) {
 800202e:	460c      	mov	r4, r1
 8002030:	1b35      	subs	r5, r6, r4
 8002032:	2c00      	cmp	r4, #0
 8002034:	443d      	add	r5, r7
 8002036:	dd0c      	ble.n	8002052 <rng_buffer+0x2a>
        uint32_t    t = rng_sample();
 8002038:	f7ff ffb6 	bl	8001fa8 <rng_sample>

        memcpy(result, &t, MIN(4, len));
 800203c:	2c04      	cmp	r4, #4
 800203e:	4622      	mov	r2, r4
//
    void
rng_buffer(uint8_t *result, int len)
{
    while(len > 0) {
        uint32_t    t = rng_sample();
 8002040:	9001      	str	r0, [sp, #4]

        memcpy(result, &t, MIN(4, len));
 8002042:	bfa8      	it	ge
 8002044:	2204      	movge	r2, #4
 8002046:	a901      	add	r1, sp, #4
 8002048:	4628      	mov	r0, r5
 800204a:	f004 fc2d 	bl	80068a8 <memcpy>

        len -= 4;
 800204e:	3c04      	subs	r4, #4
 8002050:	e7ee      	b.n	8002030 <rng_buffer+0x8>
        result += 4;
    }
}
 8002052:	b003      	add	sp, #12
 8002054:	bdf0      	pop	{r4, r5, r6, r7, pc}
	...

08002058 <_send_byte>:
    static inline void
_send_byte(uint8_t ch)
{
    // reset timeout timer (Systick)
    uint32_t    ticks = 0;
    SysTick->VAL = 0;
 8002058:	4b08      	ldr	r3, [pc, #32]	; (800207c <_send_byte+0x24>)

// _send_byte()
//
    static inline void
_send_byte(uint8_t ch)
{
 800205a:	b510      	push	{r4, lr}
    // reset timeout timer (Systick)
    uint32_t    ticks = 0;
    SysTick->VAL = 0;
 800205c:	2200      	movs	r2, #0

    while(!(MY_UART->ISR & UART_FLAG_TXE)) {
 800205e:	4c08      	ldr	r4, [pc, #32]	; (8002080 <_send_byte+0x28>)
    static inline void
_send_byte(uint8_t ch)
{
    // reset timeout timer (Systick)
    uint32_t    ticks = 0;
    SysTick->VAL = 0;
 8002060:	609a      	str	r2, [r3, #8]

    while(!(MY_UART->ISR & UART_FLAG_TXE)) {
 8002062:	220b      	movs	r2, #11
 8002064:	69e1      	ldr	r1, [r4, #28]
 8002066:	0609      	lsls	r1, r1, #24
 8002068:	d404      	bmi.n	8002074 <_send_byte+0x1c>
        // busy-wait until able to send (no fifo?)
        if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
 800206a:	6819      	ldr	r1, [r3, #0]
 800206c:	03c9      	lsls	r1, r1, #15
 800206e:	d5f9      	bpl.n	8002064 <_send_byte+0xc>
            // failsafe timeout
            ticks += 1;
            if(ticks > 10) break;
 8002070:	3a01      	subs	r2, #1
 8002072:	d1f7      	bne.n	8002064 <_send_byte+0xc>
        }
    }
    MY_UART->TDR = ch;
 8002074:	4b02      	ldr	r3, [pc, #8]	; (8002080 <_send_byte+0x28>)
 8002076:	b280      	uxth	r0, r0
 8002078:	8518      	strh	r0, [r3, #40]	; 0x28
 800207a:	bd10      	pop	{r4, pc}
 800207c:	e000e010 	.word	0xe000e010
 8002080:	40004c00 	.word	0x40004c00

08002084 <_send_bits>:

// _send_bits()
//
    static void
_send_bits(uint8_t tx)
{
 8002084:	b570      	push	{r4, r5, r6, lr}
 8002086:	4606      	mov	r6, r0
 8002088:	2508      	movs	r5, #8
    // serialize and send one byte
    uint8_t     mask = 0x1;
 800208a:	2401      	movs	r4, #1

    for(int i=0; i<8; i++, mask <<= 1) {
        uint8_t h = (tx & mask) ? BIT1 : BIT0;
 800208c:	4226      	tst	r6, r4

        _send_byte(h);
 800208e:	bf14      	ite	ne
 8002090:	207f      	movne	r0, #127	; 0x7f
 8002092:	207d      	moveq	r0, #125	; 0x7d
 8002094:	f7ff ffe0 	bl	8002058 <_send_byte>
_send_bits(uint8_t tx)
{
    // serialize and send one byte
    uint8_t     mask = 0x1;

    for(int i=0; i<8; i++, mask <<= 1) {
 8002098:	0064      	lsls	r4, r4, #1
 800209a:	3d01      	subs	r5, #1
 800209c:	b2e4      	uxtb	r4, r4
 800209e:	d1f5      	bne.n	800208c <_send_bits+0x8>
        uint8_t h = (tx & mask) ? BIT1 : BIT0;

        _send_byte(h);
    }
}
 80020a0:	bd70      	pop	{r4, r5, r6, pc}

080020a2 <_send_serialized>:

// _send_serialized()
//
    static void
_send_serialized(const uint8_t *buf, int len)
{
 80020a2:	b570      	push	{r4, r5, r6, lr}
 80020a4:	4605      	mov	r5, r0
 80020a6:	460e      	mov	r6, r1
    for(int i=0; i<len; i++) {
 80020a8:	4604      	mov	r4, r0
 80020aa:	1b63      	subs	r3, r4, r5
 80020ac:	429e      	cmp	r6, r3
 80020ae:	dd04      	ble.n	80020ba <_send_serialized+0x18>
        _send_bits(buf[i]);
 80020b0:	f814 0b01 	ldrb.w	r0, [r4], #1
 80020b4:	f7ff ffe6 	bl	8002084 <_send_bits>
 80020b8:	e7f7      	b.n	80020aa <_send_serialized+0x8>
    }
}
 80020ba:	bd70      	pop	{r4, r5, r6, pc}

080020bc <_flush_rx>:
//
    static inline void
_flush_rx(void)
{
    // reset timeout timer (Systick)
    SysTick->VAL = 0;
 80020bc:	4b0c      	ldr	r3, [pc, #48]	; (80020f0 <_flush_rx+0x34>)

    while(!(MY_UART->ISR & UART_FLAG_TC)) {
 80020be:	490d      	ldr	r1, [pc, #52]	; (80020f4 <_flush_rx+0x38>)
//
    static inline void
_flush_rx(void)
{
    // reset timeout timer (Systick)
    SysTick->VAL = 0;
 80020c0:	2200      	movs	r2, #0
 80020c2:	609a      	str	r2, [r3, #8]

    while(!(MY_UART->ISR & UART_FLAG_TC)) {
 80020c4:	69ca      	ldr	r2, [r1, #28]
 80020c6:	0652      	lsls	r2, r2, #25
 80020c8:	d402      	bmi.n	80020d0 <_flush_rx+0x14>
        // wait for last bit(byte) to be serialized and sent

        if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
 80020ca:	681a      	ldr	r2, [r3, #0]
 80020cc:	03d0      	lsls	r0, r2, #15
 80020ce:	d5f9      	bpl.n	80020c4 <_flush_rx+0x8>
  \brief   No Operation
  \details No Operation does nothing. This instruction can be used for code alignment purposes.
 */
__attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
{
  __ASM volatile ("nop");
 80020d0:	bf00      	nop
 80020d2:	bf00      	nop
 80020d4:	bf00      	nop
 80020d6:	bf00      	nop
 80020d8:	bf00      	nop
 80020da:	bf00      	nop
 80020dc:	bf00      	nop
 80020de:	bf00      	nop
    __NOP();
    __NOP();
    __NOP();

    // clear junk in rx buffer
    MY_UART->RQR = USART_RQR_RXFRQ;
 80020e0:	4b04      	ldr	r3, [pc, #16]	; (80020f4 <_flush_rx+0x38>)
 80020e2:	2208      	movs	r2, #8
 80020e4:	831a      	strh	r2, [r3, #24]

    // clear overrun error
    // clear rx timeout flag
    // clear framing error
    MY_UART->ICR = USART_ICR_ORECF | USART_ICR_RTOCF | USART_ICR_FECF;
 80020e6:	f640 020a 	movw	r2, #2058	; 0x80a
 80020ea:	621a      	str	r2, [r3, #32]
 80020ec:	4770      	bx	lr
 80020ee:	bf00      	nop
 80020f0:	e000e010 	.word	0xe000e010
 80020f4:	40004c00 	.word	0x40004c00

080020f8 <crc16_chain>:
 * \param[in] data pointer to data for which CRC should be calculated
 * \param[out] crc pointer to 16-bit CRC
 */ 
	static void
crc16_chain(uint8_t length, const uint8_t *data, uint8_t crc[2])
{
 80020f8:	b5f0      	push	{r4, r5, r6, r7, lr}
    uint16_t crc_register = 0;
    uint16_t polynom = 0x8005;
    uint8_t shift_register;
    uint8_t data_bit, crc_bit;
    
    crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8);
 80020fa:	7813      	ldrb	r3, [r2, #0]
 80020fc:	7854      	ldrb	r4, [r2, #1]
    
    for (counter = 0; counter < length; counter++) {
 80020fe:	460e      	mov	r6, r1
    uint16_t crc_register = 0;
    uint16_t polynom = 0x8005;
    uint8_t shift_register;
    uint8_t data_bit, crc_bit;
    
    crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8);
 8002100:	ea43 2304 	orr.w	r3, r3, r4, lsl #8
    
    for (counter = 0; counter < length; counter++) {
 8002104:	1a74      	subs	r4, r6, r1
 8002106:	b2e4      	uxtb	r4, r4
 8002108:	42a0      	cmp	r0, r4
 800210a:	d91a      	bls.n	8002142 <crc16_chain+0x4a>
      for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
         data_bit = (data[counter] & shift_register) ? 1 : 0;
 800210c:	f816 7b01 	ldrb.w	r7, [r6], #1
 8002110:	2508      	movs	r5, #8
 8002112:	2401      	movs	r4, #1
         crc_bit = crc_register >> 15;

         // Shift CRC to the left by 1.
         crc_register <<= 1; 

         if ((data_bit ^ crc_bit) != 0)
 8002114:	4227      	tst	r7, r4
    crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8);
    
    for (counter = 0; counter < length; counter++) {
      for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
         data_bit = (data[counter] & shift_register) ? 1 : 0;
         crc_bit = crc_register >> 15;
 8002116:	ea4f 3ed3 	mov.w	lr, r3, lsr #15

         // Shift CRC to the left by 1.
         crc_register <<= 1; 

         if ((data_bit ^ crc_bit) != 0)
 800211a:	bf18      	it	ne
 800211c:	f04f 0c01 	movne.w	ip, #1
      for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
         data_bit = (data[counter] & shift_register) ? 1 : 0;
         crc_bit = crc_register >> 15;

         // Shift CRC to the left by 1.
         crc_register <<= 1; 
 8002120:	ea4f 0343 	mov.w	r3, r3, lsl #1

         if ((data_bit ^ crc_bit) != 0)
 8002124:	bf08      	it	eq
 8002126:	f04f 0c00 	moveq.w	ip, #0
 800212a:	45f4      	cmp	ip, lr
      for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
         data_bit = (data[counter] & shift_register) ? 1 : 0;
         crc_bit = crc_register >> 15;

         // Shift CRC to the left by 1.
         crc_register <<= 1; 
 800212c:	b29b      	uxth	r3, r3

         if ((data_bit ^ crc_bit) != 0)
            crc_register ^= polynom;
 800212e:	bf1c      	itt	ne
 8002130:	f483 4300 	eorne.w	r3, r3, #32768	; 0x8000
 8002134:	f083 0305 	eorne.w	r3, r3, #5
    uint8_t data_bit, crc_bit;
    
    crc_register = (((uint16_t) crc[0]) & 0x00FF) | (((uint16_t) crc[1]) << 8);
    
    for (counter = 0; counter < length; counter++) {
      for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1) {
 8002138:	0064      	lsls	r4, r4, #1
 800213a:	3d01      	subs	r5, #1
 800213c:	b2e4      	uxtb	r4, r4
 800213e:	d1e9      	bne.n	8002114 <crc16_chain+0x1c>
 8002140:	e7e0      	b.n	8002104 <crc16_chain+0xc>
         if ((data_bit ^ crc_bit) != 0)
            crc_register ^= polynom;
      }  
    }
        
    crc[0] = (uint8_t) (crc_register & 0x00FF);
 8002142:	7013      	strb	r3, [r2, #0]
    crc[1] = (uint8_t) (crc_register >> 8);
 8002144:	0a1b      	lsrs	r3, r3, #8
 8002146:	7053      	strb	r3, [r2, #1]
 8002148:	bdf0      	pop	{r4, r5, r6, r7, pc}
	...

0800214c <ae_check_crc>:

// ae_check_crc()
//
	static bool
ae_check_crc(const uint8_t *data, uint8_t length)
{
 800214c:	b573      	push	{r0, r1, r4, r5, r6, lr}
	uint8_t obs[2] = { 0, 0 };

	if(data[0] != length) {
 800214e:	7805      	ldrb	r5, [r0, #0]
// ae_check_crc()
//
	static bool
ae_check_crc(const uint8_t *data, uint8_t length)
{
	uint8_t obs[2] = { 0, 0 };
 8002150:	2400      	movs	r4, #0

	if(data[0] != length) {
 8002152:	428d      	cmp	r5, r1

// ae_check_crc()
//
	static bool
ae_check_crc(const uint8_t *data, uint8_t length)
{
 8002154:	4606      	mov	r6, r0
	uint8_t obs[2] = { 0, 0 };
 8002156:	f88d 4004 	strb.w	r4, [sp, #4]
 800215a:	f88d 4005 	strb.w	r4, [sp, #5]

	if(data[0] != length) {
 800215e:	d004      	beq.n	800216a <ae_check_crc+0x1e>
		// length is wrong
        stats.crc_len_error++;
 8002160:	4a0d      	ldr	r2, [pc, #52]	; (8002198 <ae_check_crc+0x4c>)
 8002162:	6893      	ldr	r3, [r2, #8]
 8002164:	3301      	adds	r3, #1
 8002166:	6093      	str	r3, [r2, #8]
 8002168:	e013      	b.n	8002192 <ae_check_crc+0x46>
		return false;
	}

	crc16_chain(length-2, data, obs);
 800216a:	1ea8      	subs	r0, r5, #2

	return (obs[0] == data[length-2] && obs[1] == data[length-1]);
 800216c:	4435      	add	r5, r6
		// length is wrong
        stats.crc_len_error++;
		return false;
	}

	crc16_chain(length-2, data, obs);
 800216e:	aa01      	add	r2, sp, #4
 8002170:	4631      	mov	r1, r6
 8002172:	b2c0      	uxtb	r0, r0
 8002174:	f7ff ffc0 	bl	80020f8 <crc16_chain>

	return (obs[0] == data[length-2] && obs[1] == data[length-1]);
 8002178:	f89d 2004 	ldrb.w	r2, [sp, #4]
 800217c:	f815 3c02 	ldrb.w	r3, [r5, #-2]
 8002180:	429a      	cmp	r2, r3
 8002182:	d106      	bne.n	8002192 <ae_check_crc+0x46>
 8002184:	f89d 4005 	ldrb.w	r4, [sp, #5]
 8002188:	f815 3c01 	ldrb.w	r3, [r5, #-1]
 800218c:	1b1b      	subs	r3, r3, r4
 800218e:	425c      	negs	r4, r3
 8002190:	415c      	adcs	r4, r3
 8002192:	4620      	mov	r0, r4
}
 8002194:	b002      	add	sp, #8
 8002196:	bd70      	pop	{r4, r5, r6, pc}
 8002198:	100062b8 	.word	0x100062b8

0800219c <ae_wake>:

// ae_wake()
//
    static void
ae_wake(void)
{
 800219c:	b508      	push	{r3, lr}
    // send zero (all low), delay 2.5ms
    _send_byte(0x00);
 800219e:	2000      	movs	r0, #0
 80021a0:	f7ff ff5a 	bl	8002058 <_send_byte>

    delay_us(2500);
 80021a4:	f640 10c4 	movw	r0, #2500	; 0x9c4
 80021a8:	f000 ff4e 	bl	8003048 <delay_us>

    _flush_rx();
}
 80021ac:	e8bd 4008 	ldmia.w	sp!, {r3, lr}
    // send zero (all low), delay 2.5ms
    _send_byte(0x00);

    delay_us(2500);

    _flush_rx();
 80021b0:	f7ff bf84 	b.w	80020bc <_flush_rx>

080021b4 <ae_read_response>:
// We ignore dump extra bytes not expected, and always read until a timeout.
// Cmds to chip can be up to 155 bytes, but not clear what max len for responses.
//
    static int
ae_read_response(uint8_t *buf, int max_len)
{
 80021b4:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
    int max_expect = (max_len+1) * 8;
 80021b8:	f101 0801 	add.w	r8, r1, #1
 80021bc:	ea4f 08c8 	mov.w	r8, r8, lsl #3
// We ignore dump extra bytes not expected, and always read until a timeout.
// Cmds to chip can be up to 155 bytes, but not clear what max len for responses.
//
    static int
ae_read_response(uint8_t *buf, int max_len)
{
 80021c0:	af00      	add	r7, sp, #0
 80021c2:	4605      	mov	r5, r0
    int max_expect = (max_len+1) * 8;
    uint8_t raw[max_expect];
 80021c4:	ebad 0d08 	sub.w	sp, sp, r8

    // tell chip to write stuff to bus
    _send_bits(IOFLAG_TX);
 80021c8:	2088      	movs	r0, #136	; 0x88
// We ignore dump extra bytes not expected, and always read until a timeout.
// Cmds to chip can be up to 155 bytes, but not clear what max len for responses.
//
    static int
ae_read_response(uint8_t *buf, int max_len)
{
 80021ca:	460e      	mov	r6, r1
    int max_expect = (max_len+1) * 8;
    uint8_t raw[max_expect];

    // tell chip to write stuff to bus
    _send_bits(IOFLAG_TX);
 80021cc:	f7ff ff5a 	bl	8002084 <_send_bits>

    // kill first byte which we expect to be IOFLAG_TX echo (0x88)
    _flush_rx();
 80021d0:	f7ff ff74 	bl	80020bc <_flush_rx>
    uint32_t    ticks = 0;

    // reset timeout timer (Systick)
    SysTick->VAL = 0;

    while(!(MY_UART->ISR & UART_FLAG_RXNE) && !(MY_UART->ISR & UART_FLAG_RTOF)) {
 80021d4:	4b2c      	ldr	r3, [pc, #176]	; (8002288 <ae_read_response+0xd4>)
_read_byte(void)
{
    uint32_t    ticks = 0;

    // reset timeout timer (Systick)
    SysTick->VAL = 0;
 80021d6:	482d      	ldr	r0, [pc, #180]	; (800228c <ae_read_response+0xd8>)

    // It takes between 64 and 131us (tTURNAROUND) for the chip to recover
    // and start sending bits to us. We're blocked on reading
    // them anyway, so no need to delay. Also a danger of overruns here.

    int actual = 0;
 80021d8:	2400      	movs	r4, #0
//
    static int
ae_read_response(uint8_t *buf, int max_len)
{
    int max_expect = (max_len+1) * 8;
    uint8_t raw[max_expect];
 80021da:	46e9      	mov	r9, sp
    // It takes between 64 and 131us (tTURNAROUND) for the chip to recover
    // and start sending bits to us. We're blocked on reading
    // them anyway, so no need to delay. Also a danger of overruns here.

    int actual = 0;
    for(uint8_t *p = raw; ; actual++) {
 80021dc:	466a      	mov	r2, sp
_read_byte(void)
{
    uint32_t    ticks = 0;

    // reset timeout timer (Systick)
    SysTick->VAL = 0;
 80021de:	46a6      	mov	lr, r4
 80021e0:	469c      	mov	ip, r3
 80021e2:	f8c0 e008 	str.w	lr, [r0, #8]
 80021e6:	2105      	movs	r1, #5

    while(!(MY_UART->ISR & UART_FLAG_RXNE) && !(MY_UART->ISR & UART_FLAG_RTOF)) {
 80021e8:	f8d3 a01c 	ldr.w	sl, [r3, #28]
 80021ec:	f01a 0f20 	tst.w	sl, #32
 80021f0:	d10c      	bne.n	800220c <ae_read_response+0x58>
 80021f2:	f8d3 a01c 	ldr.w	sl, [r3, #28]
 80021f6:	f41a 6f00 	tst.w	sl, #2048	; 0x800
 80021fa:	d107      	bne.n	800220c <ae_read_response+0x58>
        // busy-waiting

        if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
 80021fc:	f8d0 a000 	ldr.w	sl, [r0]
 8002200:	f41a 3f80 	tst.w	sl, #65536	; 0x10000
 8002204:	d0f0      	beq.n	80021e8 <ae_read_response+0x34>
            ticks += 1;
            if(ticks >= 5) {
 8002206:	3901      	subs	r1, #1
 8002208:	d1ee      	bne.n	80021e8 <ae_read_response+0x34>
 800220a:	e01a      	b.n	8002242 <ae_read_response+0x8e>
                return -1;
            }
        }
    }

    if(MY_UART->ISR & UART_FLAG_RXNE) {
 800220c:	f8dc a01c 	ldr.w	sl, [ip, #28]
 8002210:	491d      	ldr	r1, [pc, #116]	; (8002288 <ae_read_response+0xd4>)
 8002212:	f01a 0f20 	tst.w	sl, #32
 8002216:	d007      	beq.n	8002228 <ae_read_response+0x74>
        return MY_UART->RDR & 0x7f;
 8002218:	8c99      	ldrh	r1, [r3, #36]	; 0x24
        int ch = _read_byte();
        if(ch < 0) {
            break;
        }

        if(actual < max_expect) {
 800221a:	4544      	cmp	r4, r8
 800221c:	f001 017f 	and.w	r1, r1, #127	; 0x7f
 8002220:	da0d      	bge.n	800223e <ae_read_response+0x8a>
            *(p++) = ch;
 8002222:	7011      	strb	r1, [r2, #0]
 8002224:	3201      	adds	r2, #1
 8002226:	e00a      	b.n	800223e <ae_read_response+0x8a>
    }

    if(MY_UART->ISR & UART_FLAG_RXNE) {
        return MY_UART->RDR & 0x7f;
    }
    if(MY_UART->ISR & UART_FLAG_RTOF) {
 8002228:	69cb      	ldr	r3, [r1, #28]
 800222a:	051b      	lsls	r3, r3, #20
 800222c:	d503      	bpl.n	8002236 <ae_read_response+0x82>
        // "fast" timeout reached, clear flag
        MY_UART->ICR = USART_ICR_RTOCF;
 800222e:	f44f 6300 	mov.w	r3, #2048	; 0x800
 8002232:	620b      	str	r3, [r1, #32]
 8002234:	e005      	b.n	8002242 <ae_read_response+0x8e>
        return -1;
    }
    INCONSISTENT("rxf");
 8002236:	4816      	ldr	r0, [pc, #88]	; (8002290 <ae_read_response+0xdc>)
 8002238:	f7fe f8c8 	bl	80003cc <fatal_error>
 800223c:	e001      	b.n	8002242 <ae_read_response+0x8e>
    // It takes between 64 and 131us (tTURNAROUND) for the chip to recover
    // and start sending bits to us. We're blocked on reading
    // them anyway, so no need to delay. Also a danger of overruns here.

    int actual = 0;
    for(uint8_t *p = raw; ; actual++) {
 800223e:	3401      	adds	r4, #1
        }

        if(actual < max_expect) {
            *(p++) = ch;
        }
    }
 8002240:	e7cf      	b.n	80021e2 <ae_read_response+0x2e>

    // Sometimes our framing is not perfect.
    // We might get a spurious bit at the leading edge (perhaps an echo
    // of part of the 0x88??) or junk at the end.
    actual &= ~7;
 8002242:	f024 0407 	bic.w	r4, r4, #7
 8002246:	1de3      	adds	r3, r4, #7
 8002248:	f109 0207 	add.w	r2, r9, #7
 800224c:	4629      	mov	r1, r5
 800224e:	4499      	add	r9, r3
// Return a deserialized byte, or -1 for timeout.
//
    static void
deserialize(const uint8_t *from, int from_len, uint8_t *into, int max_into)
{
    while(from_len > 0) {
 8002250:	454a      	cmp	r2, r9
 8002252:	d015      	beq.n	8002280 <ae_read_response+0xcc>
 8002254:	f1a2 0e08 	sub.w	lr, r2, #8
 8002258:	2301      	movs	r3, #1
 800225a:	2000      	movs	r0, #0
        uint8_t rv = 0, mask = 0x1;

        for(int i=0; i<8; i++, mask <<= 1) {
            if(from[i] == BIT1) {
 800225c:	f81e cf01 	ldrb.w	ip, [lr, #1]!
 8002260:	f1bc 0f7f 	cmp.w	ip, #127	; 0x7f
                rv |= mask;
 8002264:	bf08      	it	eq
 8002266:	4318      	orreq	r0, r3
deserialize(const uint8_t *from, int from_len, uint8_t *into, int max_into)
{
    while(from_len > 0) {
        uint8_t rv = 0, mask = 0x1;

        for(int i=0; i<8; i++, mask <<= 1) {
 8002268:	005b      	lsls	r3, r3, #1
 800226a:	4596      	cmp	lr, r2
 800226c:	b2db      	uxtb	r3, r3
 800226e:	d1f5      	bne.n	800225c <ae_read_response+0xa8>
            if(from[i] == BIT1) {
                rv |= mask;
            }
        }

        *(into++) = rv;
 8002270:	f801 0b01 	strb.w	r0, [r1], #1
 8002274:	1a73      	subs	r3, r6, r1
 8002276:	442b      	add	r3, r5
        from += 8;
        from_len -= 8;

        max_into --;
        if(max_into <= 0) break;
 8002278:	2b00      	cmp	r3, #0
 800227a:	f102 0208 	add.w	r2, r2, #8
 800227e:	dce7      	bgt.n	8002250 <ae_read_response+0x9c>
    // We might get a spurious bit at the leading edge (perhaps an echo
    // of part of the 0x88??) or junk at the end.
    actual &= ~7;
    deserialize(raw, actual, buf, max_len);

    return actual / 8;
 8002280:	10e0      	asrs	r0, r4, #3
}
 8002282:	46bd      	mov	sp, r7
 8002284:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
 8002288:	40004c00 	.word	0x40004c00
 800228c:	e000e010 	.word	0xe000e010
 8002290:	08007230 	.word	0x08007230

08002294 <ae_reset_chip>:
// ae_reset_chip()
//
    void
ae_reset_chip(void)
{
    if(ae_chip_is_setup == AE_CHIP_IS_SETUP) {
 8002294:	4b04      	ldr	r3, [pc, #16]	; (80022a8 <ae_reset_chip+0x14>)
 8002296:	681a      	ldr	r2, [r3, #0]
 8002298:	4b04      	ldr	r3, [pc, #16]	; (80022ac <ae_reset_chip+0x18>)
 800229a:	429a      	cmp	r2, r3
 800229c:	d102      	bne.n	80022a4 <ae_reset_chip+0x10>
        // "The ATECC508A goes into the low power sleep mode and ignores all
        // subsequent I/O transitions until the next wake flag. The entire volatile
        // state of the device is reset"
        _send_bits(IOFLAG_SLEEP);
 800229e:	20cc      	movs	r0, #204	; 0xcc
 80022a0:	f7ff bef0 	b.w	8002084 <_send_bits>
 80022a4:	4770      	bx	lr
 80022a6:	bf00      	nop
 80022a8:	100062dc 	.word	0x100062dc
 80022ac:	35d25d63 	.word	0x35d25d63

080022b0 <ae_setup>:
//
// Configure pins. Do not attempt to talk to chip.
//
    void
ae_setup(void)
{
 80022b0:	b507      	push	{r0, r1, r2, lr}
        .StopBits = UART_STOPBITS_1,
        .Parity = UART_PARITY_NONE,
        .Mode = UART_MODE_TX_RX,
#endif

    memset(&stats, 0, sizeof(stats));
 80022b2:	2100      	movs	r1, #0
 80022b4:	2224      	movs	r2, #36	; 0x24
 80022b6:	4816      	ldr	r0, [pc, #88]	; (8002310 <ae_setup+0x60>)
 80022b8:	f004 fb1c 	bl	80068f4 <memset>

    // enable clock to that part of chip
    __HAL_RCC_UART4_CLK_ENABLE();
 80022bc:	4b15      	ldr	r3, [pc, #84]	; (8002314 <ae_setup+0x64>)
 80022be:	6d9a      	ldr	r2, [r3, #88]	; 0x58
 80022c0:	f442 2200 	orr.w	r2, r2, #524288	; 0x80000
 80022c4:	659a      	str	r2, [r3, #88]	; 0x58
 80022c6:	6d9b      	ldr	r3, [r3, #88]	; 0x58
 80022c8:	f403 2300 	and.w	r3, r3, #524288	; 0x80000
 80022cc:	9301      	str	r3, [sp, #4]
 80022ce:	9b01      	ldr	r3, [sp, #4]
    //
    // For max clock error insensitivity:
    // OVER8==0, ONEBIT=1

    // disable UART so some other bits can be set (only while disabled)
    MY_UART->CR1 = 0;
 80022d0:	4b11      	ldr	r3, [pc, #68]	; (8002318 <ae_setup+0x68>)
 80022d2:	2200      	movs	r2, #0
 80022d4:	601a      	str	r2, [r3, #0]
    MY_UART->CR1 = 0x1000002d & ~(0
 80022d6:	4a11      	ldr	r2, [pc, #68]	; (800231c <ae_setup+0x6c>)
 80022d8:	601a      	str	r2, [r3, #0]
                                    | USART_CR1_RXNEIE
                                    | USART_CR1_IDLEIE
                                    | USART_CR1_OVER8
                                    | USART_CR1_UE);

    MY_UART->RTOR = 24;                  // timeout in bit periods: 3 chars or so
 80022da:	2218      	movs	r2, #24
 80022dc:	615a      	str	r2, [r3, #20]
    MY_UART->CR2 = USART_CR2_RTOEN;      // rx timeout enable
 80022de:	f44f 0200 	mov.w	r2, #8388608	; 0x800000
 80022e2:	605a      	str	r2, [r3, #4]
    MY_UART->CR3 = USART_CR3_HDSEL | USART_CR3_ONEBIT;
 80022e4:	f640 0208 	movw	r2, #2056	; 0x808
 80022e8:	609a      	str	r2, [r3, #8]
    MY_UART->BRR = 0x0000015b;          // 230400 bps 
 80022ea:	f240 125b 	movw	r2, #347	; 0x15b
 80022ee:	60da      	str	r2, [r3, #12]

    // clear rx timeout flag
    MY_UART->ICR = USART_ICR_RTOCF;
 80022f0:	f44f 6200 	mov.w	r2, #2048	; 0x800
 80022f4:	621a      	str	r2, [r3, #32]

    // finally enable UART
    MY_UART->CR1 |= USART_CR1_UE;
 80022f6:	681a      	ldr	r2, [r3, #0]
 80022f8:	f042 0201 	orr.w	r2, r2, #1
 80022fc:	601a      	str	r2, [r3, #0]
    
    // configure pin A0 to be AF8_UART4, PULL_NONE
    gpio_setup();
 80022fe:	f000 fec1 	bl	8003084 <gpio_setup>
    
    // mark it as ready
    ae_chip_is_setup = AE_CHIP_IS_SETUP;
 8002302:	4a07      	ldr	r2, [pc, #28]	; (8002320 <ae_setup+0x70>)
 8002304:	4b07      	ldr	r3, [pc, #28]	; (8002324 <ae_setup+0x74>)
 8002306:	601a      	str	r2, [r3, #0]
}
 8002308:	b003      	add	sp, #12
 800230a:	f85d fb04 	ldr.w	pc, [sp], #4
 800230e:	bf00      	nop
 8002310:	100062b8 	.word	0x100062b8
 8002314:	40021000 	.word	0x40021000
 8002318:	40004c00 	.word	0x40004c00
 800231c:	1000000c 	.word	0x1000000c
 8002320:	35d25d63 	.word	0x35d25d63
 8002324:	100062dc 	.word	0x100062dc

08002328 <ae_keep_alive>:

// ae_keep_alive()
//
	void
ae_keep_alive(void)
{
 8002328:	b508      	push	{r3, lr}
{
	// "The ATECC508A goes into the idle mode and ignores all subsequent
	// I/O transitions until the next wake flag. The contents of TempKey
	// and RNG Seed registers are retained."

    ae_wake();
 800232a:	f7ff ff37 	bl	800219c <ae_wake>

    _send_bits(IOFLAG_IDLE);
 800232e:	20bb      	movs	r0, #187	; 0xbb
 8002330:	f7ff fea8 	bl	8002084 <_send_bits>
	// To reset the watchdog, (1) put it into idle mode, then (2) wake it.
	ae_send_idle();

    // not clear if delay needed here?
	ae_wake();
}
 8002334:	e8bd 4008 	ldmia.w	sp!, {r3, lr}
{
	// To reset the watchdog, (1) put it into idle mode, then (2) wake it.
	ae_send_idle();

    // not clear if delay needed here?
	ae_wake();
 8002338:	f7ff bf30 	b.w	800219c <ae_wake>

0800233c <ae_read1>:
// Read a one-byte status/error code response from chip. It's wrapped as 4 bytes: 
//	(len=4) (value) (crc16) (crc16)
//
	int
ae_read1(void)
{
 800233c:	b537      	push	{r0, r1, r2, r4, r5, lr}
 800233e:	4c14      	ldr	r4, [pc, #80]	; (8002390 <ae_read1+0x54>)
 8002340:	2504      	movs	r5, #4
	uint8_t msg[4];

	for(int retry=3; retry >= 0; retry--) {
        ae_wake();
 8002342:	f7ff ff2b 	bl	800219c <ae_wake>

        // tell it we want to read a response, read it, and deserialize
        int rv = ae_read_response(msg, 4);
 8002346:	2104      	movs	r1, #4
 8002348:	eb0d 0001 	add.w	r0, sp, r1
 800234c:	f7ff ff32 	bl	80021b4 <ae_read_response>

        if(rv != 4) {
 8002350:	2804      	cmp	r0, #4

	for(int retry=3; retry >= 0; retry--) {
        ae_wake();

        // tell it we want to read a response, read it, and deserialize
        int rv = ae_read_response(msg, 4);
 8002352:	4601      	mov	r1, r0

        if(rv != 4) {
 8002354:	d003      	beq.n	800235e <ae_read1+0x22>
            ERR("rx len");
            stats.len_error++;
 8002356:	6863      	ldr	r3, [r4, #4]
 8002358:	3301      	adds	r3, #1
 800235a:	6063      	str	r3, [r4, #4]
            goto try_again;
 800235c:	e00c      	b.n	8002378 <ae_read1+0x3c>
        }

		// Check length and CRC bytes. we will retry a few times
		// if they are wrong.
		if(!ae_check_crc(msg, 4)) {
 800235e:	a801      	add	r0, sp, #4
 8002360:	f7ff fef4 	bl	800214c <ae_check_crc>
 8002364:	b918      	cbnz	r0, 800236e <ae_read1+0x32>
			ERR("bad crc");
            stats.crc_error++;
 8002366:	6823      	ldr	r3, [r4, #0]
 8002368:	3301      	adds	r3, #1
 800236a:	6023      	str	r3, [r4, #0]
			goto try_again;
 800236c:	e004      	b.n	8002378 <ae_read1+0x3c>
		}

        stats.last_resp1 = msg[1];
 800236e:	4b08      	ldr	r3, [pc, #32]	; (8002390 <ae_read1+0x54>)
 8002370:	f89d 0005 	ldrb.w	r0, [sp, #5]
 8002374:	7758      	strb	r0, [r3, #29]

		// done, and it worked; return the one byte.
		return msg[1];
 8002376:	e008      	b.n	800238a <ae_read1+0x4e>

	try_again:
        stats.l1_retry++;
 8002378:	6923      	ldr	r3, [r4, #16]
 800237a:	3301      	adds	r3, #1
 800237c:	6123      	str	r3, [r4, #16]
		ae_wake();
 800237e:	f7ff ff0d 	bl	800219c <ae_wake>
	int
ae_read1(void)
{
	uint8_t msg[4];

	for(int retry=3; retry >= 0; retry--) {
 8002382:	3d01      	subs	r5, #1
 8002384:	d1dd      	bne.n	8002342 <ae_read1+0x6>
        stats.l1_retry++;
		ae_wake();
	}

	// fail.
	return -1;
 8002386:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff
}
 800238a:	b003      	add	sp, #12
 800238c:	bd30      	pop	{r4, r5, pc}
 800238e:	bf00      	nop
 8002390:	100062b8 	.word	0x100062b8

08002394 <ae_read_n>:
//
// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead.
//
	int
ae_read_n(uint8_t len, uint8_t *body)
{
 8002394:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
    uint8_t tmp[1+len+2];
 8002398:	1cc6      	adds	r6, r0, #3
 800239a:	300a      	adds	r0, #10
 800239c:	f020 0007 	bic.w	r0, r0, #7
//
// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead.
//
	int
ae_read_n(uint8_t len, uint8_t *body)
{
 80023a0:	af00      	add	r7, sp, #0
			goto try_again;
		}

		if(!ae_check_crc(tmp, actual)) {
			ERR("bad crc");
            stats.crc_error++;
 80023a2:	4c1e      	ldr	r4, [pc, #120]	; (800241c <ae_read_n+0x88>)
// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead.
//
	int
ae_read_n(uint8_t len, uint8_t *body)
{
    uint8_t tmp[1+len+2];
 80023a4:	ebad 0d00 	sub.w	sp, sp, r0
//
// Read and check CRC over N bytes, wrapped in 3-bytes of framing overhead.
//
	int
ae_read_n(uint8_t len, uint8_t *body)
{
 80023a8:	4688      	mov	r8, r1
    uint8_t tmp[1+len+2];
 80023aa:	466d      	mov	r5, sp
 80023ac:	f04f 0904 	mov.w	r9, #4

	for(int retry=3; retry >= 0; retry--) {

        int actual = ae_read_response(tmp, len+3);
 80023b0:	4631      	mov	r1, r6
 80023b2:	4628      	mov	r0, r5
 80023b4:	f7ff fefe 	bl	80021b4 <ae_read_response>
        if(actual < 4) {
 80023b8:	2803      	cmp	r0, #3
{
    uint8_t tmp[1+len+2];

	for(int retry=3; retry >= 0; retry--) {

        int actual = ae_read_response(tmp, len+3);
 80023ba:	4682      	mov	sl, r0
        if(actual < 4) {
 80023bc:	dc03      	bgt.n	80023c6 <ae_read_n+0x32>
            ERR("too short");
            stats.short_error++;
 80023be:	68e3      	ldr	r3, [r4, #12]
 80023c0:	3301      	adds	r3, #1
 80023c2:	60e3      	str	r3, [r4, #12]
            goto try_again;
 80023c4:	e01d      	b.n	8002402 <ae_read_n+0x6e>
        }

        uint8_t resp_len = tmp[0];
 80023c6:	782a      	ldrb	r2, [r5, #0]
		if(resp_len != (len + 3)) {
 80023c8:	4296      	cmp	r6, r2
 80023ca:	d009      	beq.n	80023e0 <ae_read_n+0x4c>
            stats.len_error++;
 80023cc:	6863      	ldr	r3, [r4, #4]
            if(resp_len == 4) {
 80023ce:	2a04      	cmp	r2, #4
            goto try_again;
        }

        uint8_t resp_len = tmp[0];
		if(resp_len != (len + 3)) {
            stats.len_error++;
 80023d0:	f103 0301 	add.w	r3, r3, #1
 80023d4:	6063      	str	r3, [r4, #4]
            if(resp_len == 4) {
 80023d6:	d114      	bne.n	8002402 <ae_read_n+0x6e>
				// Probably an unexpected error. But no way to return a short read, so
				// just print out debug info.
                ERRV(msg[1], "ae errcode");
                stats.last_resp1 = tmp[1];
 80023d8:	4b10      	ldr	r3, [pc, #64]	; (800241c <ae_read_n+0x88>)
 80023da:	786a      	ldrb	r2, [r5, #1]
 80023dc:	775a      	strb	r2, [r3, #29]
 80023de:	e018      	b.n	8002412 <ae_read_n+0x7e>
            }
			ERRV(msg[0], "wr len");		 // wrong length
			goto try_again;
		}

		if(!ae_check_crc(tmp, actual)) {
 80023e0:	b2c1      	uxtb	r1, r0
 80023e2:	4628      	mov	r0, r5
 80023e4:	f7ff feb2 	bl	800214c <ae_check_crc>
 80023e8:	b918      	cbnz	r0, 80023f2 <ae_read_n+0x5e>
			ERR("bad crc");
            stats.crc_error++;
 80023ea:	6823      	ldr	r3, [r4, #0]
 80023ec:	3301      	adds	r3, #1
 80023ee:	6023      	str	r3, [r4, #0]
			goto try_again;
 80023f0:	e007      	b.n	8002402 <ae_read_n+0x6e>
		}

		// normal case: copy out body of message w/o framing
        memcpy(body, tmp+1, actual-3);
 80023f2:	f1aa 0203 	sub.w	r2, sl, #3
 80023f6:	1c69      	adds	r1, r5, #1
 80023f8:	4640      	mov	r0, r8
 80023fa:	f004 fa55 	bl	80068a8 <memcpy>
		return 0;
 80023fe:	2000      	movs	r0, #0
 8002400:	e009      	b.n	8002416 <ae_read_n+0x82>

	try_again:
        stats.ln_retry++;
 8002402:	6963      	ldr	r3, [r4, #20]
 8002404:	3301      	adds	r3, #1
 8002406:	6163      	str	r3, [r4, #20]
		ae_wake();
 8002408:	f7ff fec8 	bl	800219c <ae_wake>
	int
ae_read_n(uint8_t len, uint8_t *body)
{
    uint8_t tmp[1+len+2];

	for(int retry=3; retry >= 0; retry--) {
 800240c:	f1b9 0901 	subs.w	r9, r9, #1
 8002410:	d1ce      	bne.n	80023b0 <ae_read_n+0x1c>
	try_again:
        stats.ln_retry++;
		ae_wake();
	}

	return -1;
 8002412:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff
}
 8002416:	46bd      	mov	sp, r7
 8002418:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
 800241c:	100062b8 	.word	0x100062b8

08002420 <ae_send_n>:

// ae_send_n()
//
	int
ae_send_n(aeopcode_t opcode, uint8_t p1, uint16_t p2, const uint8_t *data, uint8_t data_len) 
{
 8002420:	b530      	push	{r4, r5, lr}
 8002422:	b085      	sub	sp, #20
 8002424:	461d      	mov	r5, r3
 8002426:	f89d 4020 	ldrb.w	r4, [sp, #32]
		uint8_t	framed_len;
		uint8_t	op;
		uint8_t	p1;
		uint8_t	p2_lsb;
		uint8_t	p2_msb;
	} known = { 
 800242a:	f88d 200c 	strb.w	r2, [sp, #12]
 800242e:	2377      	movs	r3, #119	; 0x77
 8002430:	f88d 3008 	strb.w	r3, [sp, #8]
 8002434:	1de3      	adds	r3, r4, #7
 8002436:	f88d 3009 	strb.w	r3, [sp, #9]
 800243a:	0a13      	lsrs	r3, r2, #8
 800243c:	f88d 300d 	strb.w	r3, [sp, #13]
		.p2_msb = (p2 >> 8) & 0xff,
	};

	STATIC_ASSERT(sizeof(known) == 6);

    stats.last_op = opcode;
 8002440:	4b14      	ldr	r3, [pc, #80]	; (8002494 <ae_send_n+0x74>)
		uint8_t	framed_len;
		uint8_t	op;
		uint8_t	p1;
		uint8_t	p2_lsb;
		uint8_t	p2_msb;
	} known = { 
 8002442:	f88d 000a 	strb.w	r0, [sp, #10]
		.p2_msb = (p2 >> 8) & 0xff,
	};

	STATIC_ASSERT(sizeof(known) == 6);

    stats.last_op = opcode;
 8002446:	7718      	strb	r0, [r3, #28]
    stats.last_p1 = p1;
 8002448:	7799      	strb	r1, [r3, #30]
    stats.last_p2 = p2;
 800244a:	841a      	strh	r2, [r3, #32]
		uint8_t	framed_len;
		uint8_t	op;
		uint8_t	p1;
		uint8_t	p2_lsb;
		uint8_t	p2_msb;
	} known = { 
 800244c:	f88d 100b 	strb.w	r1, [sp, #11]

    stats.last_op = opcode;
    stats.last_p1 = p1;
    stats.last_p2 = p2;

    ae_wake();
 8002450:	f7ff fea4 	bl	800219c <ae_wake>

    _send_serialized((const uint8_t *)&known, sizeof(known));
 8002454:	2106      	movs	r1, #6
 8002456:	a802      	add	r0, sp, #8
 8002458:	f7ff fe23 	bl	80020a2 <_send_serialized>

	// CRC will start from frame_len onwards
	uint8_t crc[2] = {0, 0};
 800245c:	2300      	movs	r3, #0
	crc16_chain(sizeof(known)-1, &known.framed_len, crc);
 800245e:	aa01      	add	r2, sp, #4
 8002460:	f10d 0109 	add.w	r1, sp, #9
 8002464:	2005      	movs	r0, #5
    ae_wake();

    _send_serialized((const uint8_t *)&known, sizeof(known));

	// CRC will start from frame_len onwards
	uint8_t crc[2] = {0, 0};
 8002466:	f88d 3004 	strb.w	r3, [sp, #4]
 800246a:	f88d 3005 	strb.w	r3, [sp, #5]
	crc16_chain(sizeof(known)-1, &known.framed_len, crc);
 800246e:	f7ff fe43 	bl	80020f8 <crc16_chain>

	// insert a variable-length body area (sometimes)
	if(data_len) {
 8002472:	b144      	cbz	r4, 8002486 <ae_send_n+0x66>
        _send_serialized(data, data_len);
 8002474:	4621      	mov	r1, r4
 8002476:	4628      	mov	r0, r5
 8002478:	f7ff fe13 	bl	80020a2 <_send_serialized>
		
		crc16_chain(data_len, data, crc);
 800247c:	aa01      	add	r2, sp, #4
 800247e:	4629      	mov	r1, r5
 8002480:	4620      	mov	r0, r4
 8002482:	f7ff fe39 	bl	80020f8 <crc16_chain>
	}

	// send final CRC bytes
    _send_serialized(crc, 2);
 8002486:	a801      	add	r0, sp, #4
 8002488:	2102      	movs	r1, #2
 800248a:	f7ff fe0a 	bl	80020a2 <_send_serialized>

	// done!	

	return 0;
}
 800248e:	2000      	movs	r0, #0
 8002490:	b005      	add	sp, #20
 8002492:	bd30      	pop	{r4, r5, pc}
 8002494:	100062b8 	.word	0x100062b8

08002498 <ae_send>:

// ae_send()
//
	int
ae_send(aeopcode_t opcode, uint8_t p1, uint16_t p2) 
{
 8002498:	b507      	push	{r0, r1, r2, lr}
	return ae_send_n(opcode, p1, p2, NULL, 0);
 800249a:	2300      	movs	r3, #0
 800249c:	9300      	str	r3, [sp, #0]
 800249e:	f7ff ffbf 	bl	8002420 <ae_send_n>
}
 80024a2:	b003      	add	sp, #12
 80024a4:	f85d fb04 	ldr.w	pc, [sp], #4

080024a8 <ae_delay_time>:
//
// Returns time in MS for max exec time of each command.
//
	int
ae_delay_time(aeopcode_t opcode)
{
 80024a8:	3801      	subs	r0, #1
 80024aa:	b2c0      	uxtb	r0, r0
 80024ac:	2846      	cmp	r0, #70	; 0x46
 80024ae:	bf9a      	itte	ls
 80024b0:	4b01      	ldrls	r3, [pc, #4]	; (80024b8 <ae_delay_time+0x10>)
 80024b2:	5618      	ldrsbls	r0, [r3, r0]
 80024b4:	2064      	movhi	r0, #100	; 0x64
		case OP_Write:			// 0x12
			return 26;
	}

	return 100;
}
 80024b6:	4770      	bx	lr
 80024b8:	08007238 	.word	0x08007238

080024bc <ae_delay>:
// Delay for worse-case time. Don't use in real code, since blocks
// whole system, and some commands are really long!
//
	void
ae_delay(aeopcode_t opcode)
{
 80024bc:	b508      	push	{r3, lr}
	delay_ms(ae_delay_time(opcode));
 80024be:	f7ff fff3 	bl	80024a8 <ae_delay_time>
}
 80024c2:	e8bd 4008 	ldmia.w	sp!, {r3, lr}
// whole system, and some commands are really long!
//
	void
ae_delay(aeopcode_t opcode)
{
	delay_ms(ae_delay_time(opcode));
 80024c6:	f000 bdb1 	b.w	800302c <delay_ms>

080024ca <ae_random>:
	int
ae_random(uint8_t randout[32])
{
	int rv;

	rv = ae_send(OP_Random, 0, 0);
 80024ca:	2200      	movs	r2, #0
//
// Get a fresh random number.
//
	int
ae_random(uint8_t randout[32])
{
 80024cc:	b510      	push	{r4, lr}
	int rv;

	rv = ae_send(OP_Random, 0, 0);
 80024ce:	4611      	mov	r1, r2
//
// Get a fresh random number.
//
	int
ae_random(uint8_t randout[32])
{
 80024d0:	4604      	mov	r4, r0
	int rv;

	rv = ae_send(OP_Random, 0, 0);
 80024d2:	201b      	movs	r0, #27
 80024d4:	f7ff ffe0 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 80024d8:	b940      	cbnz	r0, 80024ec <ae_random+0x22>

	ae_delay(OP_Random);
 80024da:	201b      	movs	r0, #27
 80024dc:	f7ff ffee 	bl	80024bc <ae_delay>

	rv = ae_read_n(32, randout);
 80024e0:	4621      	mov	r1, r4
 80024e2:	2020      	movs	r0, #32
	RET_IF_BAD(rv);

	return 0;
}
 80024e4:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
	rv = ae_send(OP_Random, 0, 0);
	RET_IF_BAD(rv);

	ae_delay(OP_Random);

	rv = ae_read_n(32, randout);
 80024e8:	f7ff bf54 	b.w	8002394 <ae_read_n>
	RET_IF_BAD(rv);

	return 0;
}
 80024ec:	bd10      	pop	{r4, pc}

080024ee <ae_get_info>:
//
// Do Info(p1=2) command, and return result.
//
	uint16_t
ae_get_info(void)
{
 80024ee:	b507      	push	{r0, r1, r2, lr}
	// not doing error checking here
	ae_send(OP_Info, 0x2, 0);
 80024f0:	2200      	movs	r2, #0
 80024f2:	2102      	movs	r1, #2
 80024f4:	2030      	movs	r0, #48	; 0x30
 80024f6:	f7ff ffcf 	bl	8002498 <ae_send>

	ae_delay(OP_Info);
 80024fa:	2030      	movs	r0, #48	; 0x30
 80024fc:	f7ff ffde 	bl	80024bc <ae_delay>

	// note: always returns 4 bytes, but most are garbage and unused.
	uint8_t tmp[4];
	ae_read_n(4, tmp);
 8002500:	a901      	add	r1, sp, #4
 8002502:	2004      	movs	r0, #4
 8002504:	f7ff ff46 	bl	8002394 <ae_read_n>

	return (tmp[0] << 8) | tmp[1];
 8002508:	f89d 0004 	ldrb.w	r0, [sp, #4]
 800250c:	f89d 3005 	ldrb.w	r3, [sp, #5]
}
 8002510:	ea43 2000 	orr.w	r0, r3, r0, lsl #8
 8002514:	b003      	add	sp, #12
 8002516:	f85d fb04 	ldr.w	pc, [sp], #4

0800251a <ae_load_nonce>:
// Load Tempkey with a specific value. Resulting Tempkey cannot be
// used with many commands/keys, but is needed for signing.
//
	int
ae_load_nonce(const uint8_t nonce[32])
{
 800251a:	b507      	push	{r0, r1, r2, lr}
    // p1=3
	int rv = ae_send_n(OP_Nonce, 3, 0, nonce, 32);
 800251c:	2320      	movs	r3, #32
 800251e:	9300      	str	r3, [sp, #0]
 8002520:	2200      	movs	r2, #0
 8002522:	4603      	mov	r3, r0
 8002524:	2103      	movs	r1, #3
 8002526:	2016      	movs	r0, #22
 8002528:	f7ff ff7a 	bl	8002420 <ae_send_n>
    RET_IF_BAD(rv);
 800252c:	b938      	cbnz	r0, 800253e <ae_load_nonce+0x24>

	ae_delay(OP_Nonce);
 800252e:	2016      	movs	r0, #22
 8002530:	f7ff ffc4 	bl	80024bc <ae_delay>

    return ae_read1();
}
 8002534:	b003      	add	sp, #12
 8002536:	f85d eb04 	ldr.w	lr, [sp], #4
	int rv = ae_send_n(OP_Nonce, 3, 0, nonce, 32);
    RET_IF_BAD(rv);

	ae_delay(OP_Nonce);

    return ae_read1();
 800253a:	f7ff beff 	b.w	800233c <ae_read1>
}
 800253e:	b003      	add	sp, #12
 8002540:	f85d fb04 	ldr.w	pc, [sp], #4

08002544 <ae_pick_nonce>:
// Load Tempkey with a nonce value that we both know, but
// is random and we both know is random! Tricky!
//
	int
ae_pick_nonce(const uint8_t num_in[20], uint8_t tempkey[32])
{
 8002544:	b5f0      	push	{r4, r5, r6, r7, lr}
 8002546:	b0a9      	sub	sp, #164	; 0xa4
	// we provide some 20 bytes of randomness to chip
	int	rv;

	// The chip must provide 32-bytes of random-ness,
	// so no choice in args to OP.Nonce here (due to ReqRandom).
	rv = ae_send_n(OP_Nonce, 0, 0, num_in, 20);
 8002548:	2614      	movs	r6, #20
 800254a:	2200      	movs	r2, #0
// Load Tempkey with a nonce value that we both know, but
// is random and we both know is random! Tricky!
//
	int
ae_pick_nonce(const uint8_t num_in[20], uint8_t tempkey[32])
{
 800254c:	4605      	mov	r5, r0
 800254e:	460f      	mov	r7, r1
	// we provide some 20 bytes of randomness to chip
	int	rv;

	// The chip must provide 32-bytes of random-ness,
	// so no choice in args to OP.Nonce here (due to ReqRandom).
	rv = ae_send_n(OP_Nonce, 0, 0, num_in, 20);
 8002550:	4603      	mov	r3, r0
 8002552:	9600      	str	r6, [sp, #0]
 8002554:	4611      	mov	r1, r2
 8002556:	2016      	movs	r0, #22
 8002558:	f7ff ff62 	bl	8002420 <ae_send_n>
	RET_IF_BAD(rv);
 800255c:	bb30      	cbnz	r0, 80025ac <ae_pick_nonce+0x68>

	ae_delay(OP_Nonce);
 800255e:	2016      	movs	r0, #22
 8002560:	f7ff ffac 	bl	80024bc <ae_delay>

	// Nonce command returns the RNG result, but not contents of TempKey
	uint8_t randout[32];
	rv = ae_read_n(32, randout);
 8002564:	a904      	add	r1, sp, #16
 8002566:	2020      	movs	r0, #32
 8002568:	f7ff ff14 	bl	8002394 <ae_read_n>
	RET_IF_BAD(rv);
 800256c:	4604      	mov	r4, r0
 800256e:	b9e0      	cbnz	r0, 80025aa <ae_pick_nonce+0x66>
	//
	//		return sha256(rndout + num_in + b'\x16\0\0').digest()
	//
	SHA256_CTX ctx;

    sha256_init(&ctx);
 8002570:	a80c      	add	r0, sp, #48	; 0x30
 8002572:	f002 ff1d 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, randout, 32);
 8002576:	2220      	movs	r2, #32
 8002578:	a904      	add	r1, sp, #16
 800257a:	a80c      	add	r0, sp, #48	; 0x30
 800257c:	f002 ff42 	bl	8005404 <sha256_update>
    sha256_update(&ctx, num_in, 20);
 8002580:	4632      	mov	r2, r6
 8002582:	4629      	mov	r1, r5
 8002584:	a80c      	add	r0, sp, #48	; 0x30
 8002586:	f002 ff3d 	bl	8005404 <sha256_update>
	const uint8_t fixed[3] = { 0x16, 0, 0 };
 800258a:	2316      	movs	r3, #22
    sha256_update(&ctx, fixed, 3);
 800258c:	a903      	add	r1, sp, #12
 800258e:	a80c      	add	r0, sp, #48	; 0x30
 8002590:	2203      	movs	r2, #3
	SHA256_CTX ctx;

    sha256_init(&ctx);
    sha256_update(&ctx, randout, 32);
    sha256_update(&ctx, num_in, 20);
	const uint8_t fixed[3] = { 0x16, 0, 0 };
 8002592:	f88d 300c 	strb.w	r3, [sp, #12]
 8002596:	f88d 400d 	strb.w	r4, [sp, #13]
 800259a:	f88d 400e 	strb.w	r4, [sp, #14]
    sha256_update(&ctx, fixed, 3);
 800259e:	f002 ff31 	bl	8005404 <sha256_update>

    sha256_final(&ctx, tempkey);
 80025a2:	4639      	mov	r1, r7
 80025a4:	a80c      	add	r0, sp, #48	; 0x30
 80025a6:	f002 ff4b 	bl	8005440 <sha256_final>

	ae_delay(OP_Nonce);

	// Nonce command returns the RNG result, but not contents of TempKey
	uint8_t randout[32];
	rv = ae_read_n(32, randout);
 80025aa:	4620      	mov	r0, r4
    sha256_update(&ctx, fixed, 3);

    sha256_final(&ctx, tempkey);

	return 0;
}
 80025ac:	b029      	add	sp, #164	; 0xa4
 80025ae:	bdf0      	pop	{r4, r5, r6, r7, pc}

080025b0 <ae_gendig_slot>:

// ae_gendig_slot()
//
    static int
ae_gendig_slot(int slot_num, const uint8_t slot_key[32], uint8_t digest[32])
{
 80025b0:	b5f0      	push	{r4, r5, r6, r7, lr}
 80025b2:	b0b3      	sub	sp, #204	; 0xcc
 80025b4:	4605      	mov	r5, r0
 80025b6:	460f      	mov	r7, r1

        return sha256(msg).digest()
*/
    uint8_t num_in[20], tempkey[32];

	rng_buffer(num_in, sizeof(num_in));
 80025b8:	a802      	add	r0, sp, #8
 80025ba:	2114      	movs	r1, #20

// ae_gendig_slot()
//
    static int
ae_gendig_slot(int slot_num, const uint8_t slot_key[32], uint8_t digest[32])
{
 80025bc:	4616      	mov	r6, r2

        return sha256(msg).digest()
*/
    uint8_t num_in[20], tempkey[32];

	rng_buffer(num_in, sizeof(num_in));
 80025be:	f7ff fd33 	bl	8002028 <rng_buffer>
	int rv = ae_pick_nonce(num_in, tempkey);
 80025c2:	a90e      	add	r1, sp, #56	; 0x38
 80025c4:	a802      	add	r0, sp, #8
 80025c6:	f7ff ffbd 	bl	8002544 <ae_pick_nonce>
    RET_IF_BAD(rv);
 80025ca:	2800      	cmp	r0, #0
 80025cc:	d143      	bne.n	8002656 <ae_gendig_slot+0xa6>

    //using Zone=2="Data" => "KeyID specifies a slot in the Data zone"
    rv = ae_send(OP_GenDig, 0x2, slot_num);
 80025ce:	b2aa      	uxth	r2, r5
 80025d0:	2102      	movs	r1, #2
 80025d2:	2015      	movs	r0, #21
 80025d4:	f7ff ff60 	bl	8002498 <ae_send>
    RET_IF_BAD(rv);
 80025d8:	2800      	cmp	r0, #0
 80025da:	d13c      	bne.n	8002656 <ae_gendig_slot+0xa6>

    ae_delay(OP_GenDig);
 80025dc:	2015      	movs	r0, #21
 80025de:	f7ff ff6d 	bl	80024bc <ae_delay>

    rv = ae_read1();
 80025e2:	f7ff feab 	bl	800233c <ae_read1>
    RET_IF_BAD(rv);
 80025e6:	4604      	mov	r4, r0
 80025e8:	bba0      	cbnz	r0, 8002654 <ae_gendig_slot+0xa4>

    ae_keep_alive();
 80025ea:	f7ff fe9d 	bl	8002328 <ae_keep_alive>
    //   msg = hkey + b'\x15\x02' + ustruct.pack("<H", slot_num)
    //   msg += b'\xee\x01\x23' + (b'\0'*25) + challenge
    //   assert len(msg) == 32+1+1+2+1+2+25+32
    //
	SHA256_CTX ctx;
    sha256_init(&ctx);
 80025ee:	a816      	add	r0, sp, #88	; 0x58
 80025f0:	f002 fede 	bl	80053b0 <sha256_init>

	uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 };
 80025f4:	2315      	movs	r3, #21
 80025f6:	f88d 3000 	strb.w	r3, [sp]
 80025fa:	2302      	movs	r3, #2
 80025fc:	f88d 3001 	strb.w	r3, [sp, #1]
 8002600:	23ee      	movs	r3, #238	; 0xee
 8002602:	f88d 3004 	strb.w	r3, [sp, #4]
 8002606:	2301      	movs	r3, #1
 8002608:	f88d 3005 	strb.w	r3, [sp, #5]
    uint8_t zeros[25] = { 0 };
 800260c:	2219      	movs	r2, #25
    //   assert len(msg) == 32+1+1+2+1+2+25+32
    //
	SHA256_CTX ctx;
    sha256_init(&ctx);

	uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 };
 800260e:	2323      	movs	r3, #35	; 0x23
    uint8_t zeros[25] = { 0 };
 8002610:	4621      	mov	r1, r4
 8002612:	a807      	add	r0, sp, #28
    //   assert len(msg) == 32+1+1+2+1+2+25+32
    //
	SHA256_CTX ctx;
    sha256_init(&ctx);

	uint8_t args[7] = { OP_GenDig, 2, slot_num, 0, 0xEE, 0x01, 0x23 };
 8002614:	f88d 3006 	strb.w	r3, [sp, #6]
 8002618:	f88d 5002 	strb.w	r5, [sp, #2]
 800261c:	f88d 4003 	strb.w	r4, [sp, #3]
    uint8_t zeros[25] = { 0 };
 8002620:	f004 f968 	bl	80068f4 <memset>

    sha256_update(&ctx, slot_key, 32);
 8002624:	2220      	movs	r2, #32
 8002626:	4639      	mov	r1, r7
 8002628:	a816      	add	r0, sp, #88	; 0x58
 800262a:	f002 feeb 	bl	8005404 <sha256_update>
    sha256_update(&ctx, args, sizeof(args));
 800262e:	2207      	movs	r2, #7
 8002630:	4669      	mov	r1, sp
 8002632:	a816      	add	r0, sp, #88	; 0x58
 8002634:	f002 fee6 	bl	8005404 <sha256_update>
    sha256_update(&ctx, zeros, sizeof(zeros));
 8002638:	2219      	movs	r2, #25
 800263a:	a907      	add	r1, sp, #28
 800263c:	a816      	add	r0, sp, #88	; 0x58
 800263e:	f002 fee1 	bl	8005404 <sha256_update>
    sha256_update(&ctx, tempkey, 32);
 8002642:	a90e      	add	r1, sp, #56	; 0x38
 8002644:	a816      	add	r0, sp, #88	; 0x58
 8002646:	2220      	movs	r2, #32
 8002648:	f002 fedc 	bl	8005404 <sha256_update>

    sha256_final(&ctx, digest);
 800264c:	4631      	mov	r1, r6
 800264e:	a816      	add	r0, sp, #88	; 0x58
 8002650:	f002 fef6 	bl	8005440 <sha256_final>
 8002654:	4620      	mov	r0, r4

    return 0;
}
 8002656:	b033      	add	sp, #204	; 0xcc
 8002658:	bdf0      	pop	{r4, r5, r6, r7, pc}
	...

0800265c <ae_checkmac>:

// ae_checkmac()
//
    int
ae_checkmac(uint8_t keynum, const uint8_t secret[32])
{
 800265c:	b5f0      	push	{r4, r5, r6, r7, lr}
 800265e:	b0cd      	sub	sp, #308	; 0x134

	// Since this is part of the hash, we want random bytes
	// for our "other data". Also a number for "numin" of nonce
	uint8_t od[32], numin[20];

	rng_buffer(od, sizeof(od));
 8002660:	ad0c      	add	r5, sp, #48	; 0x30

// ae_checkmac()
//
    int
ae_checkmac(uint8_t keynum, const uint8_t secret[32])
{
 8002662:	4606      	mov	r6, r0
 8002664:	460c      	mov	r4, r1

	// Since this is part of the hash, we want random bytes
	// for our "other data". Also a number for "numin" of nonce
	uint8_t od[32], numin[20];

	rng_buffer(od, sizeof(od));
 8002666:	4628      	mov	r0, r5
 8002668:	2120      	movs	r1, #32
 800266a:	f7ff fcdd 	bl	8002028 <rng_buffer>
	rng_buffer(numin, sizeof(numin));
 800266e:	2114      	movs	r1, #20
 8002670:	a807      	add	r0, sp, #28
 8002672:	f7ff fcd9 	bl	8002028 <rng_buffer>

    // need this one, want to reset watchdog to this point.
	ae_keep_alive();
 8002676:	f7ff fe57 	bl	8002328 <ae_keep_alive>

	// - load tempkey with a known nonce value
	uint8_t zeros[8] = {0};
 800267a:	2300      	movs	r3, #0
	uint8_t tempkey[32];
	rv = ae_pick_nonce(numin, tempkey);
 800267c:	a914      	add	r1, sp, #80	; 0x50
 800267e:	a807      	add	r0, sp, #28

    // need this one, want to reset watchdog to this point.
	ae_keep_alive();

	// - load tempkey with a known nonce value
	uint8_t zeros[8] = {0};
 8002680:	9305      	str	r3, [sp, #20]
 8002682:	9306      	str	r3, [sp, #24]
	uint8_t tempkey[32];
	rv = ae_pick_nonce(numin, tempkey);
 8002684:	f7ff ff5e 	bl	8002544 <ae_pick_nonce>
	RET_IF_BAD(rv);
 8002688:	2800      	cmp	r0, #0
 800268a:	d164      	bne.n	8002756 <ae_checkmac+0xfa>

	// - hash nonce and lots of other bits together
	SHA256_CTX ctx;
    sha256_init(&ctx);
 800268c:	a830      	add	r0, sp, #192	; 0xc0
 800268e:	f002 fe8f 	bl	80053b0 <sha256_init>

    // shared secret is 32 bytes from flash
    sha256_update(&ctx, secret, 32);
 8002692:	2220      	movs	r2, #32
 8002694:	4621      	mov	r1, r4
 8002696:	a830      	add	r0, sp, #192	; 0xc0
 8002698:	f002 feb4 	bl	8005404 <sha256_update>

    sha256_update(&ctx, tempkey, 32);
 800269c:	2220      	movs	r2, #32
 800269e:	a914      	add	r1, sp, #80	; 0x50
 80026a0:	a830      	add	r0, sp, #192	; 0xc0
 80026a2:	f002 feaf 	bl	8005404 <sha256_update>
    sha256_update(&ctx, &od[0], 4);
 80026a6:	2204      	movs	r2, #4
 80026a8:	4629      	mov	r1, r5
 80026aa:	a830      	add	r0, sp, #192	; 0xc0
 80026ac:	f002 feaa 	bl	8005404 <sha256_update>

    sha256_update(&ctx, zeros, 8);
 80026b0:	2208      	movs	r2, #8
 80026b2:	a905      	add	r1, sp, #20
 80026b4:	a830      	add	r0, sp, #192	; 0xc0
 80026b6:	f002 fea5 	bl	8005404 <sha256_update>

    sha256_update(&ctx, &od[4], 3);
 80026ba:	2203      	movs	r2, #3
 80026bc:	a90d      	add	r1, sp, #52	; 0x34
 80026be:	a830      	add	r0, sp, #192	; 0xc0
 80026c0:	f002 fea0 	bl	8005404 <sha256_update>

	uint8_t ee = 0xEE;
 80026c4:	23ee      	movs	r3, #238	; 0xee
    sha256_update(&ctx, &ee, 1);
 80026c6:	2201      	movs	r2, #1
 80026c8:	f10d 010f 	add.w	r1, sp, #15
 80026cc:	a830      	add	r0, sp, #192	; 0xc0

    sha256_update(&ctx, zeros, 8);

    sha256_update(&ctx, &od[4], 3);

	uint8_t ee = 0xEE;
 80026ce:	f88d 300f 	strb.w	r3, [sp, #15]
    sha256_update(&ctx, &ee, 1);
 80026d2:	f002 fe97 	bl	8005404 <sha256_update>
    sha256_update(&ctx, &od[7], 4);
 80026d6:	2204      	movs	r2, #4
 80026d8:	f10d 0137 	add.w	r1, sp, #55	; 0x37
 80026dc:	a830      	add	r0, sp, #192	; 0xc0
 80026de:	f002 fe91 	bl	8005404 <sha256_update>

	uint8_t snp[2] = { 0x01, 0x23 };
 80026e2:	4b1e      	ldr	r3, [pc, #120]	; (800275c <ae_checkmac+0x100>)
    sha256_update(&ctx, snp, 2);
 80026e4:	2202      	movs	r2, #2

	uint8_t ee = 0xEE;
    sha256_update(&ctx, &ee, 1);
    sha256_update(&ctx, &od[7], 4);

	uint8_t snp[2] = { 0x01, 0x23 };
 80026e6:	881b      	ldrh	r3, [r3, #0]
 80026e8:	f8ad 3010 	strh.w	r3, [sp, #16]
    sha256_update(&ctx, snp, 2);
 80026ec:	a904      	add	r1, sp, #16
 80026ee:	a830      	add	r0, sp, #192	; 0xc0
 80026f0:	f002 fe88 	bl	8005404 <sha256_update>
    sha256_update(&ctx, &od[11], 2);
 80026f4:	2202      	movs	r2, #2
 80026f6:	f10d 013b 	add.w	r1, sp, #59	; 0x3b
 80026fa:	a830      	add	r0, sp, #192	; 0xc0
 80026fc:	f002 fe82 	bl	8005404 <sha256_update>
		uint8_t		resp[32];
		uint8_t		od[13];
	} req;

    // content doesn't matter, but nice and visible:
    memcpy(req.ch3, copyright_msg, 32);
 8002700:	4b17      	ldr	r3, [pc, #92]	; (8002760 <ae_checkmac+0x104>)
 8002702:	aa1c      	add	r2, sp, #112	; 0x70
 8002704:	f103 0e20 	add.w	lr, r3, #32
 8002708:	4617      	mov	r7, r2
 800270a:	6818      	ldr	r0, [r3, #0]
 800270c:	6859      	ldr	r1, [r3, #4]
 800270e:	4614      	mov	r4, r2
 8002710:	c403      	stmia	r4!, {r0, r1}
 8002712:	3308      	adds	r3, #8
 8002714:	4573      	cmp	r3, lr
 8002716:	4622      	mov	r2, r4
 8002718:	d1f7      	bne.n	800270a <ae_checkmac+0xae>
	// this verifies no problem.
	int l = (ctx.blocks * 64) + ctx.npartial;
	ASSERT(l == 32+32+4+8+3+1+4+2+2);			// == 88
#endif

    sha256_final(&ctx, req.resp);
 800271a:	a924      	add	r1, sp, #144	; 0x90
 800271c:	a830      	add	r0, sp, #192	; 0xc0
 800271e:	f002 fe8f 	bl	8005440 <sha256_final>
	memcpy(req.od, od, 13);
 8002722:	e895 000f 	ldmia.w	r5, {r0, r1, r2, r3}
 8002726:	ac2c      	add	r4, sp, #176	; 0xb0
 8002728:	c407      	stmia	r4!, {r0, r1, r2}
 800272a:	7023      	strb	r3, [r4, #0]

	STATIC_ASSERT(sizeof(req) == 32 + 32 + 13);

	// Give our answer to the chip.
	rv = ae_send_n(OP_CheckMac, 0x01, keynum, (uint8_t *)&req, sizeof(req));
 800272c:	234d      	movs	r3, #77	; 0x4d
 800272e:	4632      	mov	r2, r6
 8002730:	2101      	movs	r1, #1
 8002732:	9300      	str	r3, [sp, #0]
 8002734:	2028      	movs	r0, #40	; 0x28
 8002736:	463b      	mov	r3, r7
 8002738:	f7ff fe72 	bl	8002420 <ae_send_n>

	ae_delay(OP_CheckMac);
 800273c:	2028      	movs	r0, #40	; 0x28
 800273e:	f7ff febd 	bl	80024bc <ae_delay>

	rv = ae_read1();
 8002742:	f7ff fdfb 	bl	800233c <ae_read1>
	if(rv != 0) {
 8002746:	4604      	mov	r4, r0
 8002748:	b918      	cbnz	r0, 8002752 <ae_checkmac+0xf6>
		return -1;
	}
#endif

	// just in case ... always restart watchdog timer.
	ae_keep_alive();
 800274a:	f7ff fded 	bl	8002328 <ae_keep_alive>

	return 0;
 800274e:	4620      	mov	r0, r4
 8002750:	e001      	b.n	8002756 <ae_checkmac+0xfa>
		if(rv == AE_CHECKMAC_FAIL) {
			ERR("CM fail");				// typical case: our hashs don't match
		} else {
			ERRV(rv, "CheckMac");
		}
		return -1;
 8002752:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff

	// just in case ... always restart watchdog timer.
	ae_keep_alive();

	return 0;
}
 8002756:	b04d      	add	sp, #308	; 0x134
 8002758:	bdf0      	pop	{r4, r5, r6, r7, pc}
 800275a:	bf00      	nop
 800275c:	08007236 	.word	0x08007236
 8002760:	080072c3 	.word	0x080072c3

08002764 <ae_pair_unlock>:
// Purpose is to show we are a pair of chips that belong together.
//
	int
ae_pair_unlock()
{
    return ae_checkmac(KEYNUM_pairing, rom_secrets->pairing_secret);
 8002764:	4901      	ldr	r1, [pc, #4]	; (800276c <ae_pair_unlock+0x8>)
 8002766:	2001      	movs	r0, #1
 8002768:	f7ff bf78 	b.w	800265c <ae_checkmac>
 800276c:	08007800 	.word	0x08007800

08002770 <ae_encrypted_read32>:
// ae_encrypted_read32()
//
    static int
ae_encrypted_read32(int data_slot, int blk,
                    int read_kn, const uint8_t read_key[32], uint8_t data[32])
{
 8002770:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
 8002774:	b088      	sub	sp, #32
 8002776:	4617      	mov	r7, r2
 8002778:	4698      	mov	r8, r3
 800277a:	460e      	mov	r6, r1
 800277c:	4604      	mov	r4, r0
 800277e:	9d0e      	ldr	r5, [sp, #56]	; 0x38
    uint8_t     digest[32];

    ae_keep_alive();
 8002780:	f7ff fdd2 	bl	8002328 <ae_keep_alive>
    ae_pair_unlock();
 8002784:	f7ff ffee 	bl	8002764 <ae_pair_unlock>

    int rv = ae_gendig_slot(read_kn, read_key, digest);
 8002788:	466a      	mov	r2, sp
 800278a:	4641      	mov	r1, r8
 800278c:	4638      	mov	r0, r7
 800278e:	f7ff ff0f 	bl	80025b0 <ae_gendig_slot>
    RET_IF_BAD(rv);
 8002792:	b9d0      	cbnz	r0, 80027ca <ae_encrypted_read32+0x5a>

    // read nth 32-byte "block"
    rv = ae_send(OP_Read, 0x82, (blk << 8) | (data_slot<<3));
 8002794:	00e2      	lsls	r2, r4, #3
 8002796:	ea42 2206 	orr.w	r2, r2, r6, lsl #8
 800279a:	b292      	uxth	r2, r2
 800279c:	2182      	movs	r1, #130	; 0x82
 800279e:	2002      	movs	r0, #2
 80027a0:	f7ff fe7a 	bl	8002498 <ae_send>
    RET_IF_BAD(rv);
 80027a4:	b988      	cbnz	r0, 80027ca <ae_encrypted_read32+0x5a>

    ae_delay(OP_Read);
 80027a6:	2002      	movs	r0, #2
 80027a8:	f7ff fe88 	bl	80024bc <ae_delay>

    rv = ae_read_n(32, data);
 80027ac:	4629      	mov	r1, r5
 80027ae:	2020      	movs	r0, #32
 80027b0:	f7ff fdf0 	bl	8002394 <ae_read_n>
    RET_IF_BAD(rv);
 80027b4:	b948      	cbnz	r0, 80027ca <ae_encrypted_read32+0x5a>
		*(acc) ^= *(more);
 80027b6:	782a      	ldrb	r2, [r5, #0]
 80027b8:	f81d 3000 	ldrb.w	r3, [sp, r0]
 80027bc:	3001      	adds	r0, #1
 80027be:	4053      	eors	r3, r2
bool check_equal(const void *aV, const void *bV, int len);

// XOR-mixin more bytes; acc = acc XOR more for each byte
void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
{
	for(; len; len--, more++, acc++) {
 80027c0:	2820      	cmp	r0, #32
		*(acc) ^= *(more);
 80027c2:	f805 3b01 	strb.w	r3, [r5], #1
bool check_equal(const void *aV, const void *bV, int len);

// XOR-mixin more bytes; acc = acc XOR more for each byte
void static inline xor_mixin(uint8_t *acc, const uint8_t *more, int len)
{
	for(; len; len--, more++, acc++) {
 80027c6:	d1f6      	bne.n	80027b6 <ae_encrypted_read32+0x46>

    xor_mixin(data, digest, 32);

    return 0;
 80027c8:	2000      	movs	r0, #0
}
 80027ca:	b008      	add	sp, #32
 80027cc:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

080027d0 <ae_sign>:
//
// Sign a message (already digested)
//
	int
ae_sign(uint8_t keynum, uint8_t msg_hash[32], uint8_t signature[64])
{
 80027d0:	b537      	push	{r0, r1, r2, r4, r5, lr}
 80027d2:	4605      	mov	r5, r0
	int rv = ae_load_nonce(msg_hash);
 80027d4:	4608      	mov	r0, r1
//
// Sign a message (already digested)
//
	int
ae_sign(uint8_t keynum, uint8_t msg_hash[32], uint8_t signature[64])
{
 80027d6:	4614      	mov	r4, r2
	int rv = ae_load_nonce(msg_hash);
 80027d8:	f7ff fe9f 	bl	800251a <ae_load_nonce>
	RET_IF_BAD(rv);
 80027dc:	b988      	cbnz	r0, 8002802 <ae_sign+0x32>

	rv = ae_send_n(OP_Sign, 0x80, keynum, NULL, 0);
 80027de:	9000      	str	r0, [sp, #0]
 80027e0:	4603      	mov	r3, r0
 80027e2:	462a      	mov	r2, r5
 80027e4:	2180      	movs	r1, #128	; 0x80
 80027e6:	2041      	movs	r0, #65	; 0x41
 80027e8:	f7ff fe1a 	bl	8002420 <ae_send_n>
	RET_IF_BAD(rv);
 80027ec:	b948      	cbnz	r0, 8002802 <ae_sign+0x32>

	ae_delay(OP_Sign);
 80027ee:	2041      	movs	r0, #65	; 0x41
 80027f0:	f7ff fe64 	bl	80024bc <ae_delay>

	rv = ae_read_n(64, signature);
 80027f4:	4621      	mov	r1, r4
 80027f6:	2040      	movs	r0, #64	; 0x40
	RET_IF_BAD(rv);

	return 0;
}
 80027f8:	b003      	add	sp, #12
 80027fa:	e8bd 4030 	ldmia.w	sp!, {r4, r5, lr}
	rv = ae_send_n(OP_Sign, 0x80, keynum, NULL, 0);
	RET_IF_BAD(rv);

	ae_delay(OP_Sign);

	rv = ae_read_n(64, signature);
 80027fe:	f7ff bdc9 	b.w	8002394 <ae_read_n>
	RET_IF_BAD(rv);

	return 0;
}
 8002802:	b003      	add	sp, #12
 8002804:	bd30      	pop	{r4, r5, pc}

08002806 <ae_get_counter>:
//
// Inc and return the one-way counter.
//
	int
ae_get_counter(uint32_t *result, int counter_number, bool incr)
{
 8002806:	4613      	mov	r3, r2
 8002808:	b510      	push	{r4, lr}
	int rv = ae_send(OP_Counter, incr ? 0x1 : 0x0, counter_number);
 800280a:	b28a      	uxth	r2, r1
//
// Inc and return the one-way counter.
//
	int
ae_get_counter(uint32_t *result, int counter_number, bool incr)
{
 800280c:	4604      	mov	r4, r0
	int rv = ae_send(OP_Counter, incr ? 0x1 : 0x0, counter_number);
 800280e:	4619      	mov	r1, r3
 8002810:	2024      	movs	r0, #36	; 0x24
 8002812:	f7ff fe41 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 8002816:	b940      	cbnz	r0, 800282a <ae_get_counter+0x24>

	ae_delay(OP_Counter);
 8002818:	2024      	movs	r0, #36	; 0x24
 800281a:	f7ff fe4f 	bl	80024bc <ae_delay>

	// already in correct endian
	rv = ae_read_n(4, (uint8_t *)result);
 800281e:	4621      	mov	r1, r4
 8002820:	2004      	movs	r0, #4
	RET_IF_BAD(rv);

	return 0;
}
 8002822:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
	RET_IF_BAD(rv);

	ae_delay(OP_Counter);

	// already in correct endian
	rv = ae_read_n(4, (uint8_t *)result);
 8002826:	f7ff bdb5 	b.w	8002394 <ae_read_n>
	RET_IF_BAD(rv);

	return 0;
}
 800282a:	bd10      	pop	{r4, pc}

0800282c <ae_make_mac>:
//
// Generate a MAC for the indicated key. Will be dependent on serial number.
//
	int
ae_make_mac(uint8_t keynum, uint8_t challenge[32], uint8_t mac_out[32])
{
 800282c:	b537      	push	{r0, r1, r2, r4, r5, lr}
	int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32);
 800282e:	2420      	movs	r4, #32
 8002830:	460b      	mov	r3, r1
//
// Generate a MAC for the indicated key. Will be dependent on serial number.
//
	int
ae_make_mac(uint8_t keynum, uint8_t challenge[32], uint8_t mac_out[32])
{
 8002832:	4615      	mov	r5, r2
	int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32);
 8002834:	2140      	movs	r1, #64	; 0x40
 8002836:	4602      	mov	r2, r0
 8002838:	9400      	str	r4, [sp, #0]
 800283a:	2008      	movs	r0, #8
 800283c:	f7ff fdf0 	bl	8002420 <ae_send_n>

	ae_delay(OP_MAC);
 8002840:	2008      	movs	r0, #8
 8002842:	f7ff fe3b 	bl	80024bc <ae_delay>

	rv = ae_read_n(32, mac_out);
 8002846:	4629      	mov	r1, r5
 8002848:	4620      	mov	r0, r4
	RET_IF_BAD(rv);

	return 0;
}
 800284a:	b003      	add	sp, #12
 800284c:	e8bd 4030 	ldmia.w	sp!, {r4, r5, lr}
{
	int rv = ae_send_n(OP_MAC, (1<<6), keynum, challenge, 32);

	ae_delay(OP_MAC);

	rv = ae_read_n(32, mac_out);
 8002850:	f7ff bda0 	b.w	8002394 <ae_read_n>

08002854 <ae_hmac32>:
//
// Different opcode, OP_HMAC does exactly 32 bytes w/ less steps.
//
    int
ae_hmac32(uint8_t keynum, const uint8_t msg[32], uint8_t digest[32])
{
 8002854:	b538      	push	{r3, r4, r5, lr}
 8002856:	4605      	mov	r5, r0
    // Load tempkey w/ message to be HMAC'ed
	int rv = ae_load_nonce(msg);
 8002858:	4608      	mov	r0, r1
//
// Different opcode, OP_HMAC does exactly 32 bytes w/ less steps.
//
    int
ae_hmac32(uint8_t keynum, const uint8_t msg[32], uint8_t digest[32])
{
 800285a:	4614      	mov	r4, r2
    // Load tempkey w/ message to be HMAC'ed
	int rv = ae_load_nonce(msg);
 800285c:	f7ff fe5d 	bl	800251a <ae_load_nonce>
	RET_IF_BAD(rv);
 8002860:	b970      	cbnz	r0, 8002880 <ae_hmac32+0x2c>

	// Ask for HMAC using specific key
	rv = ae_send(OP_HMAC, (1<<2) | (1<<6), keynum);
 8002862:	462a      	mov	r2, r5
 8002864:	2144      	movs	r1, #68	; 0x44
 8002866:	2011      	movs	r0, #17
 8002868:	f7ff fe16 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 800286c:	b940      	cbnz	r0, 8002880 <ae_hmac32+0x2c>

	ae_delay(OP_HMAC);
 800286e:	2011      	movs	r0, #17
 8002870:	f7ff fe24 	bl	80024bc <ae_delay>

	rv = ae_read_n(32, digest);
 8002874:	4621      	mov	r1, r4
 8002876:	2020      	movs	r0, #32
	RET_IF_BAD(rv);

	return 0;
}
 8002878:	e8bd 4038 	ldmia.w	sp!, {r3, r4, r5, lr}
	rv = ae_send(OP_HMAC, (1<<2) | (1<<6), keynum);
	RET_IF_BAD(rv);

	ae_delay(OP_HMAC);

	rv = ae_read_n(32, digest);
 800287c:	f7ff bd8a 	b.w	8002394 <ae_read_n>
	RET_IF_BAD(rv);

	return 0;
}
 8002880:	bd38      	pop	{r3, r4, r5, pc}

08002882 <ae_get_serial>:
//
// Return the serial number: it's 9 bytes, altho 3 are fixed.
//
	int
ae_get_serial(uint8_t serial[6])
{
 8002882:	b510      	push	{r4, lr}
	int rv = ae_send(OP_Read, 0x80, 0x0);
 8002884:	2200      	movs	r2, #0
//
// Return the serial number: it's 9 bytes, altho 3 are fixed.
//
	int
ae_get_serial(uint8_t serial[6])
{
 8002886:	b08c      	sub	sp, #48	; 0x30
 8002888:	4604      	mov	r4, r0
	int rv = ae_send(OP_Read, 0x80, 0x0);
 800288a:	2180      	movs	r1, #128	; 0x80
 800288c:	2002      	movs	r0, #2
 800288e:	f7ff fe03 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 8002892:	bb10      	cbnz	r0, 80028da <ae_get_serial+0x58>

	ae_delay(OP_Read);
 8002894:	2002      	movs	r0, #2
 8002896:	f7ff fe11 	bl	80024bc <ae_delay>

	uint8_t temp[32];
	rv = ae_read_n(32, temp);
 800289a:	a904      	add	r1, sp, #16
 800289c:	2020      	movs	r0, #32
 800289e:	f7ff fd79 	bl	8002394 <ae_read_n>
	RET_IF_BAD(rv);
 80028a2:	4602      	mov	r2, r0
 80028a4:	b9b0      	cbnz	r0, 80028d4 <ae_get_serial+0x52>

    // reformat to 9 bytes.
    uint8_t ts[9];
	memcpy(ts, &temp[0], 4);
	memcpy(&ts[4], &temp[8], 5);
 80028a6:	a906      	add	r1, sp, #24
 80028a8:	c903      	ldmia	r1, {r0, r1}
	rv = ae_read_n(32, temp);
	RET_IF_BAD(rv);

    // reformat to 9 bytes.
    uint8_t ts[9];
	memcpy(ts, &temp[0], 4);
 80028aa:	9b04      	ldr	r3, [sp, #16]
	memcpy(&ts[4], &temp[8], 5);
 80028ac:	9002      	str	r0, [sp, #8]

    // check the hard-coded values
    if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1;
 80028ae:	b2d8      	uxtb	r0, r3
 80028b0:	2801      	cmp	r0, #1
	rv = ae_read_n(32, temp);
	RET_IF_BAD(rv);

    // reformat to 9 bytes.
    uint8_t ts[9];
	memcpy(ts, &temp[0], 4);
 80028b2:	9301      	str	r3, [sp, #4]
	memcpy(&ts[4], &temp[8], 5);
 80028b4:	f88d 100c 	strb.w	r1, [sp, #12]

    // check the hard-coded values
    if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1;
 80028b8:	d10e      	bne.n	80028d8 <ae_get_serial+0x56>
 80028ba:	f89d 3005 	ldrb.w	r3, [sp, #5]
 80028be:	2b23      	cmp	r3, #35	; 0x23
 80028c0:	d10b      	bne.n	80028da <ae_get_serial+0x58>
 80028c2:	b2cb      	uxtb	r3, r1
 80028c4:	2bee      	cmp	r3, #238	; 0xee
 80028c6:	d108      	bne.n	80028da <ae_get_serial+0x58>

    // save only the unique bits.
    memcpy(serial, ts+2, 6);
 80028c8:	ab0c      	add	r3, sp, #48	; 0x30
 80028ca:	f853 1d2a 	ldr.w	r1, [r3, #-42]!
 80028ce:	6021      	str	r1, [r4, #0]
 80028d0:	889b      	ldrh	r3, [r3, #4]
 80028d2:	80a3      	strh	r3, [r4, #4]

	ae_delay(OP_Read);

	uint8_t temp[32];
	rv = ae_read_n(32, temp);
	RET_IF_BAD(rv);
 80028d4:	4610      	mov	r0, r2
 80028d6:	e000      	b.n	80028da <ae_get_serial+0x58>
    uint8_t ts[9];
	memcpy(ts, &temp[0], 4);
	memcpy(&ts[4], &temp[8], 5);

    // check the hard-coded values
    if((ts[0] != 0x01) || (ts[1] != 0x23) || (ts[8] != 0xEE)) return 1;
 80028d8:	2001      	movs	r0, #1

    // save only the unique bits.
    memcpy(serial, ts+2, 6);

	return 0;
}
 80028da:	b00c      	add	sp, #48	; 0x30
 80028dc:	bd10      	pop	{r4, pc}
	...

080028e0 <ae_probe>:

// ae_probe()
//
	const char *
ae_probe(void)
{
 80028e0:	b513      	push	{r0, r1, r4, lr}
ae_send_sleep(void)
{
	// "The ATECC508A goes into the low power sleep mode and ignores all
	// subsequent I/O transitions until the next wake flag. The entire volatile
	// state of the device is reset"
    ae_wake();
 80028e2:	f7ff fc5b 	bl	800219c <ae_wake>

    _send_bits(IOFLAG_SLEEP);
 80028e6:	20cc      	movs	r0, #204	; 0xcc
 80028e8:	f7ff fbcc 	bl	8002084 <_send_bits>

    // Make it sleep / wake it up.
	ae_send_sleep();

    // Wake it again (to reset state)
    ae_wake();
 80028ec:	f7ff fc56 	bl	800219c <ae_wake>

	// do a real read w/ CRC
	// with no command happening, expect 0x11: "After Wake, prior to first command"
    ae_read1();
 80028f0:	f7ff fd24 	bl	800233c <ae_read1>

	uint8_t chk = ae_read1();
 80028f4:	f7ff fd22 	bl	800233c <ae_read1>
	if(chk != AE_AFTER_WAKE) return "wk fl";
 80028f8:	b2c0      	uxtb	r0, r0
 80028fa:	2811      	cmp	r0, #17
 80028fc:	d10b      	bne.n	8002916 <ae_probe+0x36>
    }
#endif

    // read the serial number one time
    uint8_t serial[6];
	if(ae_get_serial(serial)) return "no ser";
 80028fe:	4668      	mov	r0, sp
 8002900:	f7ff ffbf 	bl	8002882 <ae_get_serial>
 8002904:	4604      	mov	r4, r0
 8002906:	b940      	cbnz	r0, 800291a <ae_probe+0x3a>
ae_send_sleep(void)
{
	// "The ATECC508A goes into the low power sleep mode and ignores all
	// subsequent I/O transitions until the next wake flag. The entire volatile
	// state of the device is reset"
    ae_wake();
 8002908:	f7ff fc48 	bl	800219c <ae_wake>

    _send_bits(IOFLAG_SLEEP);
 800290c:	20cc      	movs	r0, #204	; 0xcc
 800290e:	f7ff fbb9 	bl	8002084 <_send_bits>
	if(ae_get_serial(serial)) return "no ser";

	// put into a low-power mode, might be a bit before we come back
	ae_send_sleep();

	return NULL;
 8002912:	4620      	mov	r0, r4
 8002914:	e002      	b.n	800291c <ae_probe+0x3c>
	// do a real read w/ CRC
	// with no command happening, expect 0x11: "After Wake, prior to first command"
    ae_read1();

	uint8_t chk = ae_read1();
	if(chk != AE_AFTER_WAKE) return "wk fl";
 8002916:	4802      	ldr	r0, [pc, #8]	; (8002920 <ae_probe+0x40>)
 8002918:	e000      	b.n	800291c <ae_probe+0x3c>
    }
#endif

    // read the serial number one time
    uint8_t serial[6];
	if(ae_get_serial(serial)) return "no ser";
 800291a:	4802      	ldr	r0, [pc, #8]	; (8002924 <ae_probe+0x44>)

	// put into a low-power mode, might be a bit before we come back
	ae_send_sleep();

	return NULL;
}
 800291c:	b002      	add	sp, #8
 800291e:	bd10      	pop	{r4, pc}
 8002920:	080072e4 	.word	0x080072e4
 8002924:	080072ea 	.word	0x080072ea

08002928 <ae_slot_locks>:
//
// Read a 16-bit bitmask of which data slots are presently locked.
//
    int
ae_slot_locks(void)
{
 8002928:	b507      	push	{r0, r1, r2, lr}
    // Bytes 88, 89 in the Config zone is a bitmap of
    // which slots are locked. Have to read 4 bytes here tho
	int rv = ae_send(OP_Read, 0x00, 88/4);
 800292a:	2216      	movs	r2, #22
 800292c:	2100      	movs	r1, #0
 800292e:	2002      	movs	r0, #2
 8002930:	f7ff fdb2 	bl	8002498 <ae_send>
    if(rv) return -1;
 8002934:	b950      	cbnz	r0, 800294c <ae_slot_locks+0x24>

	ae_delay(OP_Read);
 8002936:	2002      	movs	r0, #2
 8002938:	f7ff fdc0 	bl	80024bc <ae_delay>

	uint8_t tmp[4];
	rv = ae_read_n(4, tmp);
 800293c:	a901      	add	r1, sp, #4
 800293e:	2004      	movs	r0, #4
 8002940:	f7ff fd28 	bl	8002394 <ae_read_n>
    if(rv) return -2;
 8002944:	b928      	cbnz	r0, 8002952 <ae_slot_locks+0x2a>

    // returns positive 16-bit number on success
	return (tmp[1] << 8) | tmp[0];
 8002946:	f8bd 0004 	ldrh.w	r0, [sp, #4]
 800294a:	e004      	b.n	8002956 <ae_slot_locks+0x2e>
ae_slot_locks(void)
{
    // Bytes 88, 89 in the Config zone is a bitmap of
    // which slots are locked. Have to read 4 bytes here tho
	int rv = ae_send(OP_Read, 0x00, 88/4);
    if(rv) return -1;
 800294c:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff
 8002950:	e001      	b.n	8002956 <ae_slot_locks+0x2e>

	ae_delay(OP_Read);

	uint8_t tmp[4];
	rv = ae_read_n(4, tmp);
    if(rv) return -2;
 8002952:	f06f 0001 	mvn.w	r0, #1

    // returns positive 16-bit number on success
	return (tmp[1] << 8) | tmp[0];
}
 8002956:	b003      	add	sp, #12
 8002958:	f85d fb04 	ldr.w	pc, [sp], #4

0800295c <ae_write_data_slot>:
//
// -- can also lock it.
//
    int
ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it)
{
 800295c:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    ASSERT(len == 32 || len == 72);      // limitation for this project.
 8002960:	2a20      	cmp	r2, #32
//
// -- can also lock it.
//
    int
ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it)
{
 8002962:	b085      	sub	sp, #20
 8002964:	4605      	mov	r5, r0
 8002966:	af02      	add	r7, sp, #8
 8002968:	4689      	mov	r9, r1
 800296a:	4616      	mov	r6, r2
 800296c:	461c      	mov	r4, r3
    ASSERT(len == 32 || len == 72);      // limitation for this project.
 800296e:	d004      	beq.n	800297a <ae_write_data_slot+0x1e>
 8002970:	2a48      	cmp	r2, #72	; 0x48
 8002972:	d002      	beq.n	800297a <ae_write_data_slot+0x1e>
 8002974:	4836      	ldr	r0, [pc, #216]	; (8002a50 <ae_write_data_slot+0xf4>)
 8002976:	f7fd fd29 	bl	80003cc <fatal_error>

    for(int blk=0; blk<3; blk++) {
        // have to write each "block" of 32-bytes, separately
        // zone => data
        int rv = ae_send_n(OP_Write, 0x80|2, (blk<<8) | (slot_num<<3), data+(blk*32), 32);
 800297a:	ea4f 0ac5 	mov.w	sl, r5, lsl #3
 800297e:	fa1f fa8a 	uxth.w	sl, sl
 8002982:	f04f 0800 	mov.w	r8, #0
 8002986:	f04f 0b20 	mov.w	fp, #32
 800298a:	ea4a 2208 	orr.w	r2, sl, r8, lsl #8
 800298e:	b292      	uxth	r2, r2
 8002990:	f8cd b000 	str.w	fp, [sp]
 8002994:	eb09 1348 	add.w	r3, r9, r8, lsl #5
 8002998:	2182      	movs	r1, #130	; 0x82
 800299a:	2012      	movs	r0, #18
 800299c:	f7ff fd40 	bl	8002420 <ae_send_n>
        RET_IF_BAD(rv);
 80029a0:	2800      	cmp	r0, #0
 80029a2:	d150      	bne.n	8002a46 <ae_write_data_slot+0xea>

        ae_delay(OP_Write);
 80029a4:	2012      	movs	r0, #18
 80029a6:	f7ff fd89 	bl	80024bc <ae_delay>

        rv = ae_read1();
 80029aa:	f7ff fcc7 	bl	800233c <ae_read1>
        RET_IF_BAD(rv);
 80029ae:	2800      	cmp	r0, #0
 80029b0:	d149      	bne.n	8002a46 <ae_write_data_slot+0xea>

        if(len == 32) break;
 80029b2:	2e20      	cmp	r6, #32
 80029b4:	d004      	beq.n	80029c0 <ae_write_data_slot+0x64>
    int
ae_write_data_slot(int slot_num, const uint8_t *data, int len, bool lock_it)
{
    ASSERT(len == 32 || len == 72);      // limitation for this project.

    for(int blk=0; blk<3; blk++) {
 80029b6:	f108 0801 	add.w	r8, r8, #1
 80029ba:	f1b8 0f03 	cmp.w	r8, #3
 80029be:	d1e4      	bne.n	800298a <ae_write_data_slot+0x2e>
        RET_IF_BAD(rv);

        if(len == 32) break;
    }

    if(lock_it) {
 80029c0:	2c00      	cmp	r4, #0
 80029c2:	d03f      	beq.n	8002a44 <ae_write_data_slot+0xe8>
        ASSERT(slot_num != 8);          // no support for mega slot 8
 80029c4:	2d08      	cmp	r5, #8
        RET_IF_BAD(rv);

        if(len == 32) break;
    }

    if(lock_it) {
 80029c6:	466c      	mov	r4, sp
        ASSERT(slot_num != 8);          // no support for mega slot 8
 80029c8:	d107      	bne.n	80029da <ae_write_data_slot+0x7e>
 80029ca:	4821      	ldr	r0, [pc, #132]	; (8002a50 <ae_write_data_slot+0xf4>)
 80029cc:	f7fd fcfe 	bl	80003cc <fatal_error>
        ASSERT(len == 32);
 80029d0:	2e20      	cmp	r6, #32
 80029d2:	d104      	bne.n	80029de <ae_write_data_slot+0x82>

        // Assume 36/72-byte long slot, which will be partially written, and rest
        // should be ones.
        const int slot_len = (slot_num <= 7) ? 36 : 72;
 80029d4:	f04f 0848 	mov.w	r8, #72	; 0x48
 80029d8:	e008      	b.n	80029ec <ae_write_data_slot+0x90>
        if(len == 32) break;
    }

    if(lock_it) {
        ASSERT(slot_num != 8);          // no support for mega slot 8
        ASSERT(len == 32);
 80029da:	2e20      	cmp	r6, #32
 80029dc:	d002      	beq.n	80029e4 <ae_write_data_slot+0x88>
 80029de:	481c      	ldr	r0, [pc, #112]	; (8002a50 <ae_write_data_slot+0xf4>)
 80029e0:	f7fd fcf4 	bl	80003cc <fatal_error>

        // Assume 36/72-byte long slot, which will be partially written, and rest
        // should be ones.
        const int slot_len = (slot_num <= 7) ? 36 : 72;
 80029e4:	2d07      	cmp	r5, #7
 80029e6:	dcf5      	bgt.n	80029d4 <ae_write_data_slot+0x78>
 80029e8:	f04f 0824 	mov.w	r8, #36	; 0x24
        uint8_t copy[slot_len];
 80029ec:	f108 0307 	add.w	r3, r8, #7
 80029f0:	f023 0307 	bic.w	r3, r3, #7
 80029f4:	ebad 0d03 	sub.w	sp, sp, r3
 80029f8:	ab02      	add	r3, sp, #8
        memset(copy, 0xff, slot_len);
 80029fa:	4618      	mov	r0, r3
 80029fc:	4642      	mov	r2, r8
 80029fe:	21ff      	movs	r1, #255	; 0xff
 8002a00:	f003 ff78 	bl	80068f4 <memset>

        memcpy(copy, data, len);
 8002a04:	4632      	mov	r2, r6
 8002a06:	4649      	mov	r1, r9
 8002a08:	f003 ff4e 	bl	80068a8 <memcpy>

        // calc expected CRC
        uint8_t crc[2] = {0, 0};
 8002a0c:	2200      	movs	r2, #0
        crc16_chain(slot_len, copy, crc);
 8002a0e:	4601      	mov	r1, r0
        memset(copy, 0xff, slot_len);

        memcpy(copy, data, len);

        // calc expected CRC
        uint8_t crc[2] = {0, 0};
 8002a10:	713a      	strb	r2, [r7, #4]
 8002a12:	717a      	strb	r2, [r7, #5]
        crc16_chain(slot_len, copy, crc);
 8002a14:	4640      	mov	r0, r8
 8002a16:	1d3a      	adds	r2, r7, #4
 8002a18:	f7ff fb6e 	bl	80020f8 <crc16_chain>

        // do the lock
        int rv = ae_send(OP_Lock, 2 | (slot_num << 2), (crc[1]<<8) | crc[0]);
 8002a1c:	797a      	ldrb	r2, [r7, #5]
 8002a1e:	793b      	ldrb	r3, [r7, #4]
 8002a20:	00a9      	lsls	r1, r5, #2
 8002a22:	f041 0102 	orr.w	r1, r1, #2
 8002a26:	ea43 2202 	orr.w	r2, r3, r2, lsl #8
 8002a2a:	f001 01fe 	and.w	r1, r1, #254	; 0xfe
 8002a2e:	2017      	movs	r0, #23
 8002a30:	f7ff fd32 	bl	8002498 <ae_send>
        RET_IF_BAD(rv);
 8002a34:	b920      	cbnz	r0, 8002a40 <ae_write_data_slot+0xe4>

        ae_delay(OP_Lock);
 8002a36:	2017      	movs	r0, #23
 8002a38:	f7ff fd40 	bl	80024bc <ae_delay>

        rv = ae_read1();
 8002a3c:	f7ff fc7e 	bl	800233c <ae_read1>
        uint8_t crc[2] = {0, 0};
        crc16_chain(slot_len, copy, crc);

        // do the lock
        int rv = ae_send(OP_Lock, 2 | (slot_num << 2), (crc[1]<<8) | crc[0]);
        RET_IF_BAD(rv);
 8002a40:	46a5      	mov	sp, r4
 8002a42:	e000      	b.n	8002a46 <ae_write_data_slot+0xea>

        rv = ae_read1();
        RET_IF_BAD(rv);
    }

    return 0;
 8002a44:	4620      	mov	r0, r4
}
 8002a46:	370c      	adds	r7, #12
 8002a48:	46bd      	mov	sp, r7
 8002a4a:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 8002a4e:	bf00      	nop
 8002a50:	08006960 	.word	0x08006960

08002a54 <ae_encrypted_read>:

// ae_encrypted_read()
//
    int
ae_encrypted_read(int data_slot, int read_kn, const uint8_t read_key[32], uint8_t *data, int len)
{
 8002a54:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
 8002a58:	b08a      	sub	sp, #40	; 0x28
 8002a5a:	4606      	mov	r6, r0
 8002a5c:	9c10      	ldr	r4, [sp, #64]	; 0x40
    // not clear if chip supports 4-byte encrypted reads 
    ASSERT((len == 32) || (len == 72));
 8002a5e:	2c20      	cmp	r4, #32

// ae_encrypted_read()
//
    int
ae_encrypted_read(int data_slot, int read_kn, const uint8_t read_key[32], uint8_t *data, int len)
{
 8002a60:	460f      	mov	r7, r1
 8002a62:	4690      	mov	r8, r2
 8002a64:	461d      	mov	r5, r3
    // not clear if chip supports 4-byte encrypted reads 
    ASSERT((len == 32) || (len == 72));
 8002a66:	d004      	beq.n	8002a72 <ae_encrypted_read+0x1e>
 8002a68:	2c48      	cmp	r4, #72	; 0x48
 8002a6a:	d002      	beq.n	8002a72 <ae_encrypted_read+0x1e>
 8002a6c:	4814      	ldr	r0, [pc, #80]	; (8002ac0 <ae_encrypted_read+0x6c>)
 8002a6e:	f7fd fcad 	bl	80003cc <fatal_error>

    int rv = ae_encrypted_read32(data_slot, 0, read_kn, read_key, data);
 8002a72:	9500      	str	r5, [sp, #0]
 8002a74:	4643      	mov	r3, r8
 8002a76:	463a      	mov	r2, r7
 8002a78:	2100      	movs	r1, #0
 8002a7a:	4630      	mov	r0, r6
 8002a7c:	f7ff fe78 	bl	8002770 <ae_encrypted_read32>
    RET_IF_BAD(rv);
 8002a80:	b9d0      	cbnz	r0, 8002ab8 <ae_encrypted_read+0x64>

    if(len == 32) return 0;
 8002a82:	2c20      	cmp	r4, #32
 8002a84:	d018      	beq.n	8002ab8 <ae_encrypted_read+0x64>

    rv = ae_encrypted_read32(data_slot, 1, read_kn, read_key, data+32);
 8002a86:	f105 0320 	add.w	r3, r5, #32
 8002a8a:	9300      	str	r3, [sp, #0]
 8002a8c:	463a      	mov	r2, r7
 8002a8e:	4643      	mov	r3, r8
 8002a90:	2101      	movs	r1, #1
 8002a92:	4630      	mov	r0, r6
 8002a94:	f7ff fe6c 	bl	8002770 <ae_encrypted_read32>
    RET_IF_BAD(rv);
 8002a98:	b970      	cbnz	r0, 8002ab8 <ae_encrypted_read+0x64>

    uint8_t tmp[32];
    rv = ae_encrypted_read32(data_slot, 2, read_kn, read_key, tmp);
 8002a9a:	ac02      	add	r4, sp, #8
 8002a9c:	4643      	mov	r3, r8
 8002a9e:	9400      	str	r4, [sp, #0]
 8002aa0:	463a      	mov	r2, r7
 8002aa2:	2102      	movs	r1, #2
 8002aa4:	4630      	mov	r0, r6
 8002aa6:	f7ff fe63 	bl	8002770 <ae_encrypted_read32>
    RET_IF_BAD(rv);
 8002aaa:	4603      	mov	r3, r0
 8002aac:	b918      	cbnz	r0, 8002ab6 <ae_encrypted_read+0x62>

    memcpy(data+64, tmp, 72-64);
 8002aae:	4622      	mov	r2, r4
 8002ab0:	ca03      	ldmia	r2!, {r0, r1}
 8002ab2:	6428      	str	r0, [r5, #64]	; 0x40
 8002ab4:	6469      	str	r1, [r5, #68]	; 0x44
 8002ab6:	4618      	mov	r0, r3

    return 0;
}
 8002ab8:	b00a      	add	sp, #40	; 0x28
 8002aba:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 8002abe:	bf00      	nop
 8002ac0:	08006960 	.word	0x08006960

08002ac4 <ae_encrypted_write>:
// ae_encrypted_write()
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
 8002ac4:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
	//		
	SHA256_CTX ctx;
    sha256_init(&ctx);

    uint8_t p1 = 0x80|2;        // 32 bytes into a data slot
    uint8_t p2_lsb = (data_slot << 3); 
 8002ac8:	00c0      	lsls	r0, r0, #3
// ae_encrypted_write()
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
 8002aca:	b0cf      	sub	sp, #316	; 0x13c
	//		
	SHA256_CTX ctx;
    sha256_init(&ctx);

    uint8_t p1 = 0x80|2;        // 32 bytes into a data slot
    uint8_t p2_lsb = (data_slot << 3); 
 8002acc:	b2c7      	uxtb	r7, r0
// ae_encrypted_write()
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
 8002ace:	9306      	str	r3, [sp, #24]
 8002ad0:	9e58      	ldr	r6, [sp, #352]	; 0x160
 8002ad2:	9104      	str	r1, [sp, #16]
    sha256_update(&ctx, zeros, sizeof(zeros));
    sha256_update(&ctx, data, 32);

    sha256_final(&ctx, &body[32]);

    rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body));
 8002ad4:	b2bb      	uxth	r3, r7
// ae_encrypted_write()
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
 8002ad6:	9205      	str	r2, [sp, #20]
    sha256_update(&ctx, zeros, sizeof(zeros));
    sha256_update(&ctx, data, 32);

    sha256_final(&ctx, &body[32]);

    rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body));
 8002ad8:	9303      	str	r3, [sp, #12]
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
    for(int blk=0; blk<3 && len>0; blk++, len-=32) {
 8002ada:	2500      	movs	r5, #0
        int here = MIN(32, len);

        // be nice and don't read past end of input buffer
        uint8_t     tmp[32] = { 0 };
 8002adc:	f10d 0848 	add.w	r8, sp, #72	; 0x48
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
    for(int blk=0; blk<3 && len>0; blk++, len-=32) {
 8002ae0:	2e00      	cmp	r6, #0
 8002ae2:	dd75      	ble.n	8002bd0 <ae_encrypted_write+0x10c>
        int here = MIN(32, len);

        // be nice and don't read past end of input buffer
        uint8_t     tmp[32] = { 0 };
 8002ae4:	2220      	movs	r2, #32
 8002ae6:	2100      	movs	r1, #0
 8002ae8:	4640      	mov	r0, r8
 8002aea:	f003 ff03 	bl	80068f4 <memset>
        memcpy(tmp, data+(32*blk), here);
 8002aee:	9b06      	ldr	r3, [sp, #24]
 8002af0:	2e20      	cmp	r6, #32
 8002af2:	4632      	mov	r2, r6
 8002af4:	eb03 1145 	add.w	r1, r3, r5, lsl #5
 8002af8:	bfa8      	it	ge
 8002afa:	2220      	movge	r2, #32
 8002afc:	4640      	mov	r0, r8
 8002afe:	f003 fed3 	bl	80068a8 <memcpy>
ae_encrypted_write32(int data_slot, int blk, int write_kn,
                        const uint8_t write_key[32], const uint8_t data[32])
{
    uint8_t digest[32];

    ae_keep_alive();
 8002b02:	f7ff fc11 	bl	8002328 <ae_keep_alive>
    ae_pair_unlock();
 8002b06:	f7ff fe2d 	bl	8002764 <ae_pair_unlock>

    // generate a hash over shared secret and rng
    int rv = ae_gendig_slot(write_kn, write_key, digest);
 8002b0a:	aa1a      	add	r2, sp, #104	; 0x68
 8002b0c:	9905      	ldr	r1, [sp, #20]
 8002b0e:	9804      	ldr	r0, [sp, #16]
 8002b10:	f7ff fd4e 	bl	80025b0 <ae_gendig_slot>
    RET_IF_BAD(rv);
 8002b14:	2800      	cmp	r0, #0
 8002b16:	d155      	bne.n	8002bc4 <ae_encrypted_write+0x100>
 8002b18:	4604      	mov	r4, r0

    // encrypt the data to be written, and append an authenticating MAC
    uint8_t body[32 + 32];

    for(int i=0; i<32; i++) {
        body[i] = data[i] ^ digest[i];
 8002b1a:	ab1a      	add	r3, sp, #104	; 0x68
 8002b1c:	f818 1004 	ldrb.w	r1, [r8, r4]
 8002b20:	5ce2      	ldrb	r2, [r4, r3]
 8002b22:	f10d 0b88 	add.w	fp, sp, #136	; 0x88
 8002b26:	404a      	eors	r2, r1
 8002b28:	f804 200b 	strb.w	r2, [r4, fp]
    RET_IF_BAD(rv);

    // encrypt the data to be written, and append an authenticating MAC
    uint8_t body[32 + 32];

    for(int i=0; i<32; i++) {
 8002b2c:	3401      	adds	r4, #1
 8002b2e:	2c20      	cmp	r4, #32
 8002b30:	d1f3      	bne.n	8002b1a <ae_encrypted_write+0x56>
	//	    + (b'\0'*25)
	//	    + new_value)
	//	assert len(msg) == 32+1+1+2+1+2+25+32
	//		
	SHA256_CTX ctx;
    sha256_init(&ctx);
 8002b32:	a832      	add	r0, sp, #200	; 0xc8
 8002b34:	9307      	str	r3, [sp, #28]
 8002b36:	f002 fc3b 	bl	80053b0 <sha256_init>

    uint8_t p1 = 0x80|2;        // 32 bytes into a data slot
    uint8_t p2_lsb = (data_slot << 3); 
    uint8_t p2_msb = blk;

	uint8_t args[7] = { OP_Write, p1, p2_lsb, p2_msb, 0xEE, 0x01, 0x23 };
 8002b3a:	22ee      	movs	r2, #238	; 0xee
 8002b3c:	f88d 2028 	strb.w	r2, [sp, #40]	; 0x28
 8002b40:	2201      	movs	r2, #1
 8002b42:	f88d 2029 	strb.w	r2, [sp, #41]	; 0x29
 8002b46:	2223      	movs	r2, #35	; 0x23
 8002b48:	f04f 0912 	mov.w	r9, #18
 8002b4c:	f04f 0a82 	mov.w	sl, #130	; 0x82
 8002b50:	f88d 202a 	strb.w	r2, [sp, #42]	; 0x2a
    uint8_t zeros[25] = { 0 };
 8002b54:	2100      	movs	r1, #0
 8002b56:	2219      	movs	r2, #25
 8002b58:	a80b      	add	r0, sp, #44	; 0x2c

    uint8_t p1 = 0x80|2;        // 32 bytes into a data slot
    uint8_t p2_lsb = (data_slot << 3); 
    uint8_t p2_msb = blk;

	uint8_t args[7] = { OP_Write, p1, p2_lsb, p2_msb, 0xEE, 0x01, 0x23 };
 8002b5a:	f88d 9024 	strb.w	r9, [sp, #36]	; 0x24
 8002b5e:	f88d a025 	strb.w	sl, [sp, #37]	; 0x25
 8002b62:	f88d 7026 	strb.w	r7, [sp, #38]	; 0x26
 8002b66:	f88d 5027 	strb.w	r5, [sp, #39]	; 0x27
    uint8_t zeros[25] = { 0 };
 8002b6a:	f003 fec3 	bl	80068f4 <memset>

    sha256_update(&ctx, digest, 32);
 8002b6e:	9b07      	ldr	r3, [sp, #28]
 8002b70:	4622      	mov	r2, r4
 8002b72:	4619      	mov	r1, r3
 8002b74:	a832      	add	r0, sp, #200	; 0xc8
 8002b76:	f002 fc45 	bl	8005404 <sha256_update>
    sha256_update(&ctx, args, sizeof(args));
 8002b7a:	2207      	movs	r2, #7
 8002b7c:	a909      	add	r1, sp, #36	; 0x24
 8002b7e:	a832      	add	r0, sp, #200	; 0xc8
 8002b80:	f002 fc40 	bl	8005404 <sha256_update>
    sha256_update(&ctx, zeros, sizeof(zeros));
 8002b84:	2219      	movs	r2, #25
 8002b86:	a90b      	add	r1, sp, #44	; 0x2c
 8002b88:	a832      	add	r0, sp, #200	; 0xc8
 8002b8a:	f002 fc3b 	bl	8005404 <sha256_update>
    sha256_update(&ctx, data, 32);
 8002b8e:	4622      	mov	r2, r4
 8002b90:	4641      	mov	r1, r8
 8002b92:	a832      	add	r0, sp, #200	; 0xc8
 8002b94:	f002 fc36 	bl	8005404 <sha256_update>

    sha256_final(&ctx, &body[32]);
 8002b98:	a92a      	add	r1, sp, #168	; 0xa8
 8002b9a:	a832      	add	r0, sp, #200	; 0xc8
 8002b9c:	f002 fc50 	bl	8005440 <sha256_final>

    rv = ae_send_n(OP_Write, p1, (p2_msb << 8) | p2_lsb, body, sizeof(body));
 8002ba0:	9903      	ldr	r1, [sp, #12]
 8002ba2:	022a      	lsls	r2, r5, #8
 8002ba4:	2340      	movs	r3, #64	; 0x40
 8002ba6:	f402 427f 	and.w	r2, r2, #65280	; 0xff00
 8002baa:	9300      	str	r3, [sp, #0]
 8002bac:	430a      	orrs	r2, r1
 8002bae:	465b      	mov	r3, fp
 8002bb0:	4651      	mov	r1, sl
 8002bb2:	4648      	mov	r0, r9
 8002bb4:	f7ff fc34 	bl	8002420 <ae_send_n>
    RET_IF_BAD(rv);
 8002bb8:	b920      	cbnz	r0, 8002bc4 <ae_encrypted_write+0x100>

    ae_delay(OP_Write);
 8002bba:	4648      	mov	r0, r9
 8002bbc:	f7ff fc7e 	bl	80024bc <ae_delay>

    rv = ae_read1();
 8002bc0:	f7ff fbbc 	bl	800233c <ae_read1>
        // be nice and don't read past end of input buffer
        uint8_t     tmp[32] = { 0 };
        memcpy(tmp, data+(32*blk), here);

        int rv = ae_encrypted_write32(data_slot, blk, write_kn, write_key, tmp);
        RET_IF_BAD(rv);
 8002bc4:	b928      	cbnz	r0, 8002bd2 <ae_encrypted_write+0x10e>
//
    int
ae_encrypted_write(int data_slot, int write_kn, const uint8_t write_key[32],
                        const uint8_t *data, int len)
{
    for(int blk=0; blk<3 && len>0; blk++, len-=32) {
 8002bc6:	3501      	adds	r5, #1
 8002bc8:	2d03      	cmp	r5, #3
 8002bca:	f1a6 0620 	sub.w	r6, r6, #32
 8002bce:	d187      	bne.n	8002ae0 <ae_encrypted_write+0x1c>

        int rv = ae_encrypted_write32(data_slot, blk, write_kn, write_key, tmp);
        RET_IF_BAD(rv);
    }

    return 0;
 8002bd0:	2000      	movs	r0, #0
}
 8002bd2:	b04f      	add	sp, #316	; 0x13c
 8002bd4:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}

08002bd8 <ae_read_data_slot>:

// ae_read_data_slot()
//
    int
ae_read_data_slot(int slot_num, uint8_t *data, int len)
{
 8002bd8:	b570      	push	{r4, r5, r6, lr}
    ASSERT((len == 4) || (len == 32) || (len == 72));
 8002bda:	2a04      	cmp	r2, #4

// ae_read_data_slot()
//
    int
ae_read_data_slot(int slot_num, uint8_t *data, int len)
{
 8002bdc:	b088      	sub	sp, #32
 8002bde:	4605      	mov	r5, r0
 8002be0:	460c      	mov	r4, r1
 8002be2:	4616      	mov	r6, r2
    ASSERT((len == 4) || (len == 32) || (len == 72));
 8002be4:	d007      	beq.n	8002bf6 <ae_read_data_slot+0x1e>
 8002be6:	2a20      	cmp	r2, #32
 8002be8:	d040      	beq.n	8002c6c <ae_read_data_slot+0x94>
 8002bea:	2a48      	cmp	r2, #72	; 0x48
 8002bec:	d03e      	beq.n	8002c6c <ae_read_data_slot+0x94>
 8002bee:	4821      	ldr	r0, [pc, #132]	; (8002c74 <ae_read_data_slot+0x9c>)
 8002bf0:	f7fd fbec 	bl	80003cc <fatal_error>
 8002bf4:	e03a      	b.n	8002c6c <ae_read_data_slot+0x94>

    // zone => data
    // only reading first block of 32 bytes. ignore the rest
    int rv = ae_send(OP_Read, (len == 4 ? 0x00 : 0x80) | 2, (slot_num<<3));
 8002bf6:	2102      	movs	r1, #2
 8002bf8:	00ed      	lsls	r5, r5, #3
 8002bfa:	b2ad      	uxth	r5, r5
 8002bfc:	462a      	mov	r2, r5
 8002bfe:	2002      	movs	r0, #2
 8002c00:	f7ff fc4a 	bl	8002498 <ae_send>
    RET_IF_BAD(rv);
 8002c04:	bba0      	cbnz	r0, 8002c70 <ae_read_data_slot+0x98>

    ae_delay(OP_Read);
 8002c06:	2002      	movs	r0, #2
 8002c08:	f7ff fc58 	bl	80024bc <ae_delay>

    rv = ae_read_n((len == 4) ? 4 : 32, data);
 8002c0c:	2e04      	cmp	r6, #4
 8002c0e:	bf0c      	ite	eq
 8002c10:	2004      	moveq	r0, #4
 8002c12:	2020      	movne	r0, #32
 8002c14:	4621      	mov	r1, r4
 8002c16:	f7ff fbbd 	bl	8002394 <ae_read_n>
    RET_IF_BAD(rv);
 8002c1a:	bb48      	cbnz	r0, 8002c70 <ae_read_data_slot+0x98>

    if(len == 72) {
 8002c1c:	2e48      	cmp	r6, #72	; 0x48
 8002c1e:	d127      	bne.n	8002c70 <ae_read_data_slot+0x98>
        // read second block
        int rv = ae_send(OP_Read, 0x82, (1<<8) | (slot_num<<3));
 8002c20:	f445 7280 	orr.w	r2, r5, #256	; 0x100
 8002c24:	2182      	movs	r1, #130	; 0x82
 8002c26:	2002      	movs	r0, #2
 8002c28:	f7ff fc36 	bl	8002498 <ae_send>
        RET_IF_BAD(rv);
 8002c2c:	bb00      	cbnz	r0, 8002c70 <ae_read_data_slot+0x98>

        ae_delay(OP_Read);
 8002c2e:	2002      	movs	r0, #2
 8002c30:	f7ff fc44 	bl	80024bc <ae_delay>

        rv = ae_read_n(32, data+32);
 8002c34:	f104 0120 	add.w	r1, r4, #32
 8002c38:	2020      	movs	r0, #32
 8002c3a:	f7ff fbab 	bl	8002394 <ae_read_n>
        RET_IF_BAD(rv);
 8002c3e:	b9b8      	cbnz	r0, 8002c70 <ae_read_data_slot+0x98>

        // read third block, but only using part of it
        uint8_t     tmp[32];
        rv = ae_send(OP_Read, 0x82, (2<<8) | (slot_num<<3));
 8002c40:	f445 7200 	orr.w	r2, r5, #512	; 0x200
 8002c44:	2182      	movs	r1, #130	; 0x82
 8002c46:	2002      	movs	r0, #2
 8002c48:	f7ff fc26 	bl	8002498 <ae_send>
        RET_IF_BAD(rv);
 8002c4c:	b980      	cbnz	r0, 8002c70 <ae_read_data_slot+0x98>

        ae_delay(OP_Read);
 8002c4e:	2002      	movs	r0, #2
 8002c50:	f7ff fc34 	bl	80024bc <ae_delay>

        rv = ae_read_n(32, tmp);
 8002c54:	4669      	mov	r1, sp
 8002c56:	2020      	movs	r0, #32
 8002c58:	f7ff fb9c 	bl	8002394 <ae_read_n>
        RET_IF_BAD(rv);
 8002c5c:	4603      	mov	r3, r0
 8002c5e:	b918      	cbnz	r0, 8002c68 <ae_read_data_slot+0x90>

        memcpy(data+64, tmp, 72-64);
 8002c60:	466a      	mov	r2, sp
 8002c62:	ca03      	ldmia	r2!, {r0, r1}
 8002c64:	6420      	str	r0, [r4, #64]	; 0x40
 8002c66:	6461      	str	r1, [r4, #68]	; 0x44
 8002c68:	4618      	mov	r0, r3
 8002c6a:	e001      	b.n	8002c70 <ae_read_data_slot+0x98>
{
    ASSERT((len == 4) || (len == 32) || (len == 72));

    // zone => data
    // only reading first block of 32 bytes. ignore the rest
    int rv = ae_send(OP_Read, (len == 4 ? 0x00 : 0x80) | 2, (slot_num<<3));
 8002c6c:	2182      	movs	r1, #130	; 0x82
 8002c6e:	e7c3      	b.n	8002bf8 <ae_read_data_slot+0x20>

        memcpy(data+64, tmp, 72-64);
    }

    return 0;
}
 8002c70:	b008      	add	sp, #32
 8002c72:	bd70      	pop	{r4, r5, r6, pc}
 8002c74:	08006960 	.word	0x08006960

08002c78 <ae_sha256>:

// ae_sha256()
//
	int
ae_sha256(const uint8_t *msg, int msg_len, uint8_t digest[32])
{
 8002c78:	e92d 41f3 	stmdb	sp!, {r0, r1, r4, r5, r6, r7, r8, lr}
 8002c7c:	4616      	mov	r6, r2
	// setup
	int rv = ae_send(OP_SHA, 0x00, 0);
 8002c7e:	2200      	movs	r2, #0

// ae_sha256()
//
	int
ae_sha256(const uint8_t *msg, int msg_len, uint8_t digest[32])
{
 8002c80:	4607      	mov	r7, r0
 8002c82:	460d      	mov	r5, r1
	// setup
	int rv = ae_send(OP_SHA, 0x00, 0);
 8002c84:	2047      	movs	r0, #71	; 0x47
 8002c86:	4611      	mov	r1, r2
 8002c88:	f7ff fc06 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 8002c8c:	bb90      	cbnz	r0, 8002cf4 <ae_sha256+0x7c>

	ae_delay(OP_SHA);
 8002c8e:	2047      	movs	r0, #71	; 0x47
 8002c90:	f7ff fc14 	bl	80024bc <ae_delay>

	rv = ae_read1();
 8002c94:	f7ff fb52 	bl	800233c <ae_read1>
	if(rv != AE_COMMAND_OK) return -1;
 8002c98:	b918      	cbnz	r0, 8002ca2 <ae_sha256+0x2a>
 8002c9a:	462c      	mov	r4, r5

	while(msg_len >= 64) {
		rv = ae_send_n(OP_SHA, 0x01, 64, msg, 64);
 8002c9c:	f04f 0840 	mov.w	r8, #64	; 0x40
 8002ca0:	e012      	b.n	8002cc8 <ae_sha256+0x50>
	RET_IF_BAD(rv);

	ae_delay(OP_SHA);

	rv = ae_read1();
	if(rv != AE_COMMAND_OK) return -1;
 8002ca2:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff
 8002ca6:	e025      	b.n	8002cf4 <ae_sha256+0x7c>

	while(msg_len >= 64) {
		rv = ae_send_n(OP_SHA, 0x01, 64, msg, 64);
 8002ca8:	f8cd 8000 	str.w	r8, [sp]
 8002cac:	2240      	movs	r2, #64	; 0x40
 8002cae:	2101      	movs	r1, #1
 8002cb0:	2047      	movs	r0, #71	; 0x47
 8002cb2:	f7ff fbb5 	bl	8002420 <ae_send_n>
		RET_IF_BAD(rv);
 8002cb6:	b9e8      	cbnz	r0, 8002cf4 <ae_sha256+0x7c>
		ae_delay(OP_SHA);
 8002cb8:	2047      	movs	r0, #71	; 0x47
 8002cba:	f7ff fbff 	bl	80024bc <ae_delay>

		rv = ae_read1();
 8002cbe:	f7ff fb3d 	bl	800233c <ae_read1>
		if(rv != AE_COMMAND_OK) return -1;
 8002cc2:	2800      	cmp	r0, #0
 8002cc4:	d1ed      	bne.n	8002ca2 <ae_sha256+0x2a>

		msg += 64;
		msg_len -= 64;
 8002cc6:	3c40      	subs	r4, #64	; 0x40
 8002cc8:	1b2b      	subs	r3, r5, r4
	ae_delay(OP_SHA);

	rv = ae_read1();
	if(rv != AE_COMMAND_OK) return -1;

	while(msg_len >= 64) {
 8002cca:	2c3f      	cmp	r4, #63	; 0x3f
 8002ccc:	443b      	add	r3, r7
 8002cce:	dceb      	bgt.n	8002ca8 <ae_sha256+0x30>
		msg += 64;
		msg_len -= 64;
	}

	// finalize, with final 0 to 63 bytes
	rv = ae_send_n(OP_SHA, 0x02, msg_len, msg, msg_len);
 8002cd0:	b2e2      	uxtb	r2, r4
 8002cd2:	9200      	str	r2, [sp, #0]
 8002cd4:	2102      	movs	r1, #2
 8002cd6:	b2a2      	uxth	r2, r4
 8002cd8:	2047      	movs	r0, #71	; 0x47
 8002cda:	f7ff fba1 	bl	8002420 <ae_send_n>
	RET_IF_BAD(rv);
 8002cde:	b948      	cbnz	r0, 8002cf4 <ae_sha256+0x7c>

	ae_delay(OP_SHA);
 8002ce0:	2047      	movs	r0, #71	; 0x47
 8002ce2:	f7ff fbeb 	bl	80024bc <ae_delay>

	rv = ae_read_n(32, digest);
 8002ce6:	4631      	mov	r1, r6
 8002ce8:	2020      	movs	r0, #32
	RET_IF_BAD(rv);

	return 0;
}
 8002cea:	b002      	add	sp, #8
 8002cec:	e8bd 41f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, lr}
	rv = ae_send_n(OP_SHA, 0x02, msg_len, msg, msg_len);
	RET_IF_BAD(rv);

	ae_delay(OP_SHA);

	rv = ae_read_n(32, digest);
 8002cf0:	f7ff bb50 	b.w	8002394 <ae_read_n>
	RET_IF_BAD(rv);

	return 0;
}
 8002cf4:	b002      	add	sp, #8
 8002cf6:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

08002cfa <ae_set_gpio>:

// ae_set_gpio()
//
    int
ae_set_gpio(int state)
{
 8002cfa:	b513      	push	{r0, r1, r4, lr}
    // 1=turn on green, 0=red light (if not yet configured to be secure)
    int rv = ae_send(OP_Info, 3, 2 | (!!state));
 8002cfc:	2800      	cmp	r0, #0
 8002cfe:	bf14      	ite	ne
 8002d00:	2203      	movne	r2, #3
 8002d02:	2202      	moveq	r2, #2
 8002d04:	4604      	mov	r4, r0
 8002d06:	2103      	movs	r1, #3
 8002d08:	2030      	movs	r0, #48	; 0x30
 8002d0a:	f7ff fbc5 	bl	8002498 <ae_send>
	RET_IF_BAD(rv);
 8002d0e:	b968      	cbnz	r0, 8002d2c <ae_set_gpio+0x32>

	ae_delay(OP_Info);
 8002d10:	2030      	movs	r0, #48	; 0x30
 8002d12:	f7ff fbd3 	bl	80024bc <ae_delay>

    // "Always return the current state in the first byte followed by three bytes of 0x00"
    // - simple 1/0, in LSB.
    uint8_t resp[4];

    rv = ae_read_n(4, resp);
 8002d16:	a901      	add	r1, sp, #4
 8002d18:	2004      	movs	r0, #4
 8002d1a:	f7ff fb3b 	bl	8002394 <ae_read_n>
	RET_IF_BAD(rv);
 8002d1e:	b928      	cbnz	r0, 8002d2c <ae_set_gpio+0x32>

    return (resp[0] != state) ? -1 : 0;
 8002d20:	f89d 0004 	ldrb.w	r0, [sp, #4]
 8002d24:	1b00      	subs	r0, r0, r4
 8002d26:	bf18      	it	ne
 8002d28:	f04f 30ff 	movne.w	r0, #4294967295	; 0xffffffff
}
 8002d2c:	b002      	add	sp, #8
 8002d2e:	bd10      	pop	{r4, pc}

08002d30 <ae_set_gpio_secure>:
//
// Set the GPIO using secure hash generated somehow already.
//
    int
ae_set_gpio_secure(uint8_t digest[32])
{
 8002d30:	b510      	push	{r4, lr}
 8002d32:	4604      	mov	r4, r0
    ae_pair_unlock();
 8002d34:	f7ff fd16 	bl	8002764 <ae_pair_unlock>
    ae_checkmac(KEYNUM_firmware, digest);
 8002d38:	4621      	mov	r1, r4
 8002d3a:	200e      	movs	r0, #14
 8002d3c:	f7ff fc8e 	bl	800265c <ae_checkmac>

    return ae_set_gpio(1);
 8002d40:	2001      	movs	r0, #1
}
 8002d42:	e8bd 4010 	ldmia.w	sp!, {r4, lr}
ae_set_gpio_secure(uint8_t digest[32])
{
    ae_pair_unlock();
    ae_checkmac(KEYNUM_firmware, digest);

    return ae_set_gpio(1);
 8002d46:	f7ff bfd8 	b.w	8002cfa <ae_set_gpio>

08002d4a <ae_get_gpio>:
//
// Do Info(p1=3) command, and return result.
//
	uint8_t
ae_get_gpio(void)
{
 8002d4a:	b507      	push	{r0, r1, r2, lr}
	// not doing error checking here
	ae_send(OP_Info, 0x3, 0);
 8002d4c:	2200      	movs	r2, #0
 8002d4e:	2103      	movs	r1, #3
 8002d50:	2030      	movs	r0, #48	; 0x30
 8002d52:	f7ff fba1 	bl	8002498 <ae_send>

	ae_delay(OP_Info);
 8002d56:	2030      	movs	r0, #48	; 0x30
 8002d58:	f7ff fbb0 	bl	80024bc <ae_delay>

	// note: always returns 4 bytes, but most are garbage and unused.
	uint8_t tmp[4];
	ae_read_n(4, tmp);
 8002d5c:	a901      	add	r1, sp, #4
 8002d5e:	2004      	movs	r0, #4
 8002d60:	f7ff fb18 	bl	8002394 <ae_read_n>

	return tmp[0];
}
 8002d64:	f89d 0004 	ldrb.w	r0, [sp, #4]
 8002d68:	b003      	add	sp, #12
 8002d6a:	f85d fb04 	ldr.w	pc, [sp], #4

08002d6e <ae_read_config_word>:
//
// Read a 4-byte area from config area, or -1 if fail.
//
    int
ae_read_config_word(int offset, uint8_t *dest)
{
 8002d6e:	b510      	push	{r4, lr}
    offset &= 0x7f;

    // read 32 bits (aligned)
	int rv = ae_send(OP_Read, 0x00, offset/4);
 8002d70:	f3c0 0284 	ubfx	r2, r0, #2, #5
//
// Read a 4-byte area from config area, or -1 if fail.
//
    int
ae_read_config_word(int offset, uint8_t *dest)
{
 8002d74:	460c      	mov	r4, r1
    offset &= 0x7f;

    // read 32 bits (aligned)
	int rv = ae_send(OP_Read, 0x00, offset/4);
 8002d76:	2002      	movs	r0, #2
 8002d78:	2100      	movs	r1, #0
 8002d7a:	f7ff fb8d 	bl	8002498 <ae_send>
    if(rv) return -1;
 8002d7e:	b958      	cbnz	r0, 8002d98 <ae_read_config_word+0x2a>

	ae_delay(OP_Read);
 8002d80:	2002      	movs	r0, #2
 8002d82:	f7ff fb9b 	bl	80024bc <ae_delay>

	rv = ae_read_n(4, dest);
 8002d86:	4621      	mov	r1, r4
 8002d88:	2004      	movs	r0, #4
 8002d8a:	f7ff fb03 	bl	8002394 <ae_read_n>
    if(rv) return -1;
 8002d8e:	3000      	adds	r0, #0
 8002d90:	bf18      	it	ne
 8002d92:	2001      	movne	r0, #1
 8002d94:	4240      	negs	r0, r0
 8002d96:	bd10      	pop	{r4, pc}
{
    offset &= 0x7f;

    // read 32 bits (aligned)
	int rv = ae_send(OP_Read, 0x00, offset/4);
    if(rv) return -1;
 8002d98:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff

	rv = ae_read_n(4, dest);
    if(rv) return -1;

    return 0;
}
 8002d9c:	bd10      	pop	{r4, pc}
	...

08002da0 <ae_read_config_byte>:
//
// Read a byte from config area.
//
    int
ae_read_config_byte(int offset)
{
 8002da0:	b513      	push	{r0, r1, r4, lr}
	uint8_t tmp[4];

    ae_read_config_word(offset, tmp);
 8002da2:	a901      	add	r1, sp, #4
//
// Read a byte from config area.
//
    int
ae_read_config_byte(int offset)
{
 8002da4:	4604      	mov	r4, r0
	uint8_t tmp[4];

    ae_read_config_word(offset, tmp);
 8002da6:	f7ff ffe2 	bl	8002d6e <ae_read_config_word>

	return tmp[offset % 4];
 8002daa:	4b07      	ldr	r3, [pc, #28]	; (8002dc8 <ae_read_config_byte+0x28>)
 8002dac:	4023      	ands	r3, r4
 8002dae:	2b00      	cmp	r3, #0
 8002db0:	bfbe      	ittt	lt
 8002db2:	f103 33ff 	addlt.w	r3, r3, #4294967295	; 0xffffffff
 8002db6:	f063 0303 	ornlt	r3, r3, #3
 8002dba:	3301      	addlt	r3, #1
 8002dbc:	aa02      	add	r2, sp, #8
 8002dbe:	4413      	add	r3, r2
}
 8002dc0:	f813 0c04 	ldrb.w	r0, [r3, #-4]
 8002dc4:	b002      	add	sp, #8
 8002dc6:	bd10      	pop	{r4, pc}
 8002dc8:	80000003 	.word	0x80000003

08002dcc <ae_destroy_key>:

// ae_destroy_key()
//
    int
ae_destroy_key(int keynum)
{
 8002dcc:	b510      	push	{r4, lr}
 8002dce:	b090      	sub	sp, #64	; 0x40
	uint8_t numin[20];

	// Load tempkey with a known (random) nonce value
	rng_buffer(numin, sizeof(numin));
 8002dd0:	2114      	movs	r1, #20

// ae_destroy_key()
//
    int
ae_destroy_key(int keynum)
{
 8002dd2:	4604      	mov	r4, r0
	uint8_t numin[20];

	// Load tempkey with a known (random) nonce value
	rng_buffer(numin, sizeof(numin));
 8002dd4:	a803      	add	r0, sp, #12
 8002dd6:	f7ff f927 	bl	8002028 <rng_buffer>
	int rv = ae_send_n(OP_Nonce, 0, 0, numin, 20);
 8002dda:	2314      	movs	r3, #20
 8002ddc:	2200      	movs	r2, #0
 8002dde:	9300      	str	r3, [sp, #0]
 8002de0:	4611      	mov	r1, r2
 8002de2:	ab03      	add	r3, sp, #12
 8002de4:	2016      	movs	r0, #22
 8002de6:	f7ff fb1b 	bl	8002420 <ae_send_n>
	RET_IF_BAD(rv);
 8002dea:	b9a8      	cbnz	r0, 8002e18 <ae_destroy_key+0x4c>

	ae_delay(OP_Nonce);
 8002dec:	2016      	movs	r0, #22
 8002dee:	f7ff fb65 	bl	80024bc <ae_delay>

	// Nonce command returns the RNG result, not contents of TempKey,
    // but since we are destroying, no need to calculate what it is.
	uint8_t randout[32];
	rv = ae_read_n(32, randout);
 8002df2:	a908      	add	r1, sp, #32
 8002df4:	2020      	movs	r0, #32
 8002df6:	f7ff facd 	bl	8002394 <ae_read_n>
	RET_IF_BAD(rv);
 8002dfa:	b968      	cbnz	r0, 8002e18 <ae_destroy_key+0x4c>

    // do a "DeriveKey" operation, based on that!
	rv = ae_send(OP_DeriveKey, 0x00, keynum);
 8002dfc:	4601      	mov	r1, r0
 8002dfe:	b2a2      	uxth	r2, r4
 8002e00:	201c      	movs	r0, #28
 8002e02:	f7ff fb49 	bl	8002498 <ae_send>
    if(rv) return -1;
 8002e06:	b928      	cbnz	r0, 8002e14 <ae_destroy_key+0x48>

	ae_delay(OP_DeriveKey);
 8002e08:	201c      	movs	r0, #28
 8002e0a:	f7ff fb57 	bl	80024bc <ae_delay>

    return ae_read1();
 8002e0e:	f7ff fa95 	bl	800233c <ae_read1>
 8002e12:	e001      	b.n	8002e18 <ae_destroy_key+0x4c>
	rv = ae_read_n(32, randout);
	RET_IF_BAD(rv);

    // do a "DeriveKey" operation, based on that!
	rv = ae_send(OP_DeriveKey, 0x00, keynum);
    if(rv) return -1;
 8002e14:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff

	ae_delay(OP_DeriveKey);

    return ae_read1();
}
 8002e18:	b010      	add	sp, #64	; 0x40
 8002e1a:	bd10      	pop	{r4, pc}

08002e1c <ae_setup_config>:
// us to write the (existing) pairing secret into, they would see the pairing
// secret in cleartext. They could then restore original chip and access freely.
//
    int
ae_setup_config(void)
{
 8002e1c:	b530      	push	{r4, r5, lr}
    // Is data zone is locked?
    // Allow rest of function to happen if it's not.

    //  0x55 = unlocked; 0x00 = locked
    bool data_locked = (ae_read_config_byte(86) != 0x55);
 8002e1e:	2056      	movs	r0, #86	; 0x56
// us to write the (existing) pairing secret into, they would see the pairing
// secret in cleartext. They could then restore original chip and access freely.
//
    int
ae_setup_config(void)
{
 8002e20:	b0c1      	sub	sp, #260	; 0x104
    // Is data zone is locked?
    // Allow rest of function to happen if it's not.

    //  0x55 = unlocked; 0x00 = locked
    bool data_locked = (ae_read_config_byte(86) != 0x55);
 8002e22:	f7ff ffbd 	bl	8002da0 <ae_read_config_byte>
    if(data_locked) return 0;       // basically success
 8002e26:	2855      	cmp	r0, #85	; 0x55
 8002e28:	f040 80e2 	bne.w	8002ff0 <ae_setup_config+0x1d4>
 8002e2c:	2400      	movs	r4, #0
    // in there, so start with some readout.
    uint8_t config[4 * 32];

    for(int blk=0; blk<4; blk++) {
        // read 32 bytes (aligned) from config "zone"
        int rv = ae_send(OP_Read, 0x80, blk<<3);
 8002e2e:	00e2      	lsls	r2, r4, #3
 8002e30:	b292      	uxth	r2, r2
 8002e32:	2180      	movs	r1, #128	; 0x80
 8002e34:	2002      	movs	r0, #2
 8002e36:	f7ff fb2f 	bl	8002498 <ae_send>
        if(rv) return EIO;
 8002e3a:	b108      	cbz	r0, 8002e40 <ae_setup_config+0x24>
 8002e3c:	2005      	movs	r0, #5
 8002e3e:	e0e5      	b.n	800300c <ae_setup_config+0x1f0>

        ae_delay(OP_Read);
 8002e40:	2002      	movs	r0, #2
 8002e42:	f7ff fb3b 	bl	80024bc <ae_delay>

        rv = ae_read_n(32, &config[32*blk]);
 8002e46:	ab20      	add	r3, sp, #128	; 0x80
 8002e48:	eb03 1144 	add.w	r1, r3, r4, lsl #5
 8002e4c:	2020      	movs	r0, #32
 8002e4e:	f7ff faa1 	bl	8002394 <ae_read_n>
        if(rv) return EIO;
 8002e52:	2800      	cmp	r0, #0
 8002e54:	d1f2      	bne.n	8002e3c <ae_setup_config+0x20>
    // To lock, we need a CRC over whole thing, but we
    // only set a few values... plus the serial number is
    // in there, so start with some readout.
    uint8_t config[4 * 32];

    for(int blk=0; blk<4; blk++) {
 8002e56:	3401      	adds	r4, #1
 8002e58:	2c04      	cmp	r4, #4
 8002e5a:	d1e8      	bne.n	8002e2e <ae_setup_config+0x12>
        rv = ae_read_n(32, &config[32*blk]);
        if(rv) return EIO;
    }

    // verify some fixed values
    ASSERT(config[0] == 0x01);
 8002e5c:	f89d 3080 	ldrb.w	r3, [sp, #128]	; 0x80
 8002e60:	2b01      	cmp	r3, #1
 8002e62:	d002      	beq.n	8002e6a <ae_setup_config+0x4e>
 8002e64:	486a      	ldr	r0, [pc, #424]	; (8003010 <ae_setup_config+0x1f4>)
 8002e66:	f7fd fab1 	bl	80003cc <fatal_error>
    ASSERT(config[1] == 0x23);
 8002e6a:	f89d 3081 	ldrb.w	r3, [sp, #129]	; 0x81
 8002e6e:	2b23      	cmp	r3, #35	; 0x23
 8002e70:	d002      	beq.n	8002e78 <ae_setup_config+0x5c>
 8002e72:	4867      	ldr	r0, [pc, #412]	; (8003010 <ae_setup_config+0x1f4>)
 8002e74:	f7fd faaa 	bl	80003cc <fatal_error>
    ASSERT(config[12] == 0xee);
 8002e78:	f89d 308c 	ldrb.w	r3, [sp, #140]	; 0x8c
 8002e7c:	2bee      	cmp	r3, #238	; 0xee
 8002e7e:	d002      	beq.n	8002e86 <ae_setup_config+0x6a>
 8002e80:	4863      	ldr	r0, [pc, #396]	; (8003010 <ae_setup_config+0x1f4>)
 8002e82:	f7fd faa3 	bl	80003cc <fatal_error>

    uint8_t serial[9];
	memcpy(serial, &config[0], 4);
 8002e86:	ac40      	add	r4, sp, #256	; 0x100
 8002e88:	9b20      	ldr	r3, [sp, #128]	; 0x80
 8002e8a:	f844 3df4 	str.w	r3, [r4, #-244]!
	memcpy(&serial[4], &config[8], 5);
 8002e8e:	ab22      	add	r3, sp, #136	; 0x88
 8002e90:	e893 0003 	ldmia.w	r3, {r0, r1}
 8002e94:	9004      	str	r0, [sp, #16]
 8002e96:	f88d 1014 	strb.w	r1, [sp, #20]

    if(check_all_ones(rom_secrets->ae_serial_number, 9)) {
 8002e9a:	485e      	ldr	r0, [pc, #376]	; (8003014 <ae_setup_config+0x1f8>)
 8002e9c:	2109      	movs	r1, #9
 8002e9e:	f7ff f85b 	bl	8001f58 <check_all_ones>
 8002ea2:	b110      	cbz	r0, 8002eaa <ae_setup_config+0x8e>
        // flash is empty; remember this serial number
        flash_save_ae_serial(serial);
 8002ea4:	4620      	mov	r0, r4
 8002ea6:	f7fe ff1f 	bl	8001ce8 <flash_save_ae_serial>
    }

    if(!check_equal(rom_secrets->ae_serial_number, serial, 9)) {
 8002eaa:	2209      	movs	r2, #9
 8002eac:	4621      	mov	r1, r4
 8002eae:	4859      	ldr	r0, [pc, #356]	; (8003014 <ae_setup_config+0x1f8>)
 8002eb0:	f7ff f86a 	bl	8001f88 <check_equal>
 8002eb4:	2800      	cmp	r0, #0
 8002eb6:	f000 80a5 	beq.w	8003004 <ae_setup_config+0x1e8>
    // - pick RNG value for words secret (and forget it)
    // - set all PIN values to known value (zeros)
    // - set all money secrets to knonw value (zeros)
    // - lock the data zone

    if(config[87] == 0x55) {
 8002eba:	f89d 30d7 	ldrb.w	r3, [sp, #215]	; 0xd7
 8002ebe:	2b55      	cmp	r3, #85	; 0x55
 8002ec0:	d14f      	bne.n	8002f62 <ae_setup_config+0x146>
        static const uint8_t    config_2[] = AE_CHIP_CONFIG_2;

        STATIC_ASSERT(sizeof(config_1) == 84-16);
        STATIC_ASSERT(sizeof(config_2) == 128-90);

        memcpy(&config[16], config_1, sizeof(config_1));
 8002ec2:	2244      	movs	r2, #68	; 0x44
 8002ec4:	4954      	ldr	r1, [pc, #336]	; (8003018 <ae_setup_config+0x1fc>)
 8002ec6:	a824      	add	r0, sp, #144	; 0x90
 8002ec8:	f003 fcee 	bl	80068a8 <memcpy>
        memcpy(&config[90], config_2, sizeof(config_2));
 8002ecc:	4b53      	ldr	r3, [pc, #332]	; (800301c <ae_setup_config+0x200>)
 8002ece:	f10d 02da 	add.w	r2, sp, #218	; 0xda
 8002ed2:	f103 0124 	add.w	r1, r3, #36	; 0x24
 8002ed6:	f853 0b04 	ldr.w	r0, [r3], #4
 8002eda:	f842 0b04 	str.w	r0, [r2], #4
 8002ede:	428b      	cmp	r3, r1
 8002ee0:	d1f9      	bne.n	8002ed6 <ae_setup_config+0xba>
 8002ee2:	881b      	ldrh	r3, [r3, #0]
 8002ee4:	8013      	strh	r3, [r2, #0]
//
    static int
ae_config_write(const uint8_t config[128])
{
    // send all 128 bytes, less some that can't be written.
    for(int n=16; n<128; n+= 4) {
 8002ee6:	2410      	movs	r4, #16
        }

        // Must work on words, since can't write to most of the complete blocks.
        //  args = write_params(block=n//32, offset=n//4, is_config=True)
        //  p2 = (block << 3) | offset
        int rv = ae_send_n(OP_Write, 0, n/4, &config[n], 4);
 8002ee8:	2504      	movs	r5, #4
    static int
ae_config_write(const uint8_t config[128])
{
    // send all 128 bytes, less some that can't be written.
    for(int n=16; n<128; n+= 4) {
        if((n >= 84) && (n < 90)) {
 8002eea:	f1a4 0354 	sub.w	r3, r4, #84	; 0x54
 8002eee:	2b05      	cmp	r3, #5
 8002ef0:	d803      	bhi.n	8002efa <ae_setup_config+0xde>
//
    static int
ae_config_write(const uint8_t config[128])
{
    // send all 128 bytes, less some that can't be written.
    for(int n=16; n<128; n+= 4) {
 8002ef2:	3404      	adds	r4, #4
 8002ef4:	2c80      	cmp	r4, #128	; 0x80
 8002ef6:	d1f8      	bne.n	8002eea <ae_setup_config+0xce>
 8002ef8:	e013      	b.n	8002f22 <ae_setup_config+0x106>
        }

        // Must work on words, since can't write to most of the complete blocks.
        //  args = write_params(block=n//32, offset=n//4, is_config=True)
        //  p2 = (block << 3) | offset
        int rv = ae_send_n(OP_Write, 0, n/4, &config[n], 4);
 8002efa:	ab20      	add	r3, sp, #128	; 0x80
 8002efc:	9500      	str	r5, [sp, #0]
 8002efe:	4423      	add	r3, r4
 8002f00:	f3c4 028f 	ubfx	r2, r4, #2, #16
 8002f04:	2100      	movs	r1, #0
 8002f06:	2012      	movs	r0, #18
 8002f08:	f7ff fa8a 	bl	8002420 <ae_send_n>
        RET_IF_BAD(rv);
 8002f0c:	b930      	cbnz	r0, 8002f1c <ae_setup_config+0x100>

        ae_delay(OP_Write);
 8002f0e:	2012      	movs	r0, #18
 8002f10:	f7ff fad4 	bl	80024bc <ae_delay>
    
		rv = ae_read1();
 8002f14:	f7ff fa12 	bl	800233c <ae_read1>
        if(rv) return rv;
 8002f18:	2800      	cmp	r0, #0
 8002f1a:	d0ea      	beq.n	8002ef2 <ae_setup_config+0xd6>
        memcpy(&config[16], config_1, sizeof(config_1));
        memcpy(&config[90], config_2, sizeof(config_2));

        // write it.
        if(ae_config_write(config)) {
            INCONSISTENT("conf wr");
 8002f1c:	4840      	ldr	r0, [pc, #256]	; (8003020 <ae_setup_config+0x204>)
 8002f1e:	f7fd fa55 	bl	80003cc <fatal_error>
        }

        ae_keep_alive();
 8002f22:	f7ff fa01 	bl	8002328 <ae_keep_alive>
//
    static int
ae_lock_config_zone(const uint8_t config[128])
{
    // calc expected CRC
    uint8_t crc[2] = {0, 0};
 8002f26:	2400      	movs	r4, #0

    crc16_chain(128, config, crc);
 8002f28:	aa0e      	add	r2, sp, #56	; 0x38
 8002f2a:	a920      	add	r1, sp, #128	; 0x80
 8002f2c:	2080      	movs	r0, #128	; 0x80
//
    static int
ae_lock_config_zone(const uint8_t config[128])
{
    // calc expected CRC
    uint8_t crc[2] = {0, 0};
 8002f2e:	f88d 4038 	strb.w	r4, [sp, #56]	; 0x38
 8002f32:	f88d 4039 	strb.w	r4, [sp, #57]	; 0x39

    crc16_chain(128, config, crc);
 8002f36:	f7ff f8df 	bl	80020f8 <crc16_chain>

    // do the lock: mode=0
    int rv = ae_send(OP_Lock, 0x0, (crc[1]<<8) | crc[0]);
 8002f3a:	f89d 2039 	ldrb.w	r2, [sp, #57]	; 0x39
 8002f3e:	f89d 3038 	ldrb.w	r3, [sp, #56]	; 0x38
 8002f42:	4621      	mov	r1, r4
 8002f44:	ea43 2202 	orr.w	r2, r3, r2, lsl #8
 8002f48:	2017      	movs	r0, #23
 8002f4a:	f7ff faa5 	bl	8002498 <ae_send>
    RET_IF_BAD(rv);
 8002f4e:	b920      	cbnz	r0, 8002f5a <ae_setup_config+0x13e>

    ae_delay(OP_Lock);
 8002f50:	2017      	movs	r0, #23
 8002f52:	f7ff fab3 	bl	80024bc <ae_delay>

    return ae_read1();
 8002f56:	f7ff f9f1 	bl	800233c <ae_read1>
        }

        ae_keep_alive();

        // lock config zone
        if(ae_lock_config_zone(config)) {
 8002f5a:	b110      	cbz	r0, 8002f62 <ae_setup_config+0x146>
            INCONSISTENT("conf lock");
 8002f5c:	4830      	ldr	r0, [pc, #192]	; (8003020 <ae_setup_config+0x204>)
 8002f5e:	f7fd fa35 	bl	80003cc <fatal_error>
    // The datazone still unlocked, so no encryption needed (nor possible).

    
    // will use zeros for all PIN codes, and secret starting values
    uint8_t     zeros[72];
    memset(zeros, 0, sizeof(zeros));
 8002f62:	2248      	movs	r2, #72	; 0x48
 8002f64:	2100      	movs	r1, #0
 8002f66:	a80e      	add	r0, sp, #56	; 0x38
 8002f68:	f003 fcc4 	bl	80068f4 <memset>

    for(int kn=0; kn<16; kn++) {
 8002f6c:	2400      	movs	r4, #0
        ae_keep_alive();
 8002f6e:	f7ff f9db 	bl	8002328 <ae_keep_alive>
 8002f72:	1c65      	adds	r5, r4, #1

        switch(kn) {
 8002f74:	2c0e      	cmp	r4, #14
 8002f76:	d82d      	bhi.n	8002fd4 <ae_setup_config+0x1b8>
 8002f78:	e8df f004 	tbb	[pc, r4]
 8002f7c:	1f100827 	.word	0x1f100827
 8002f80:	1f1f1f1f 	.word	0x1f1f1f1f
 8002f84:	2222221f 	.word	0x2222221f
 8002f88:	1f22      	.short	0x1f22
 8002f8a:	1f          	.byte	0x1f
 8002f8b:	00          	.byte	0x00
            default:
            case 15: break;

            case KEYNUM_pairing:
                if(ae_write_data_slot(kn, rom_secrets->pairing_secret, 32, false)) {
 8002f8c:	4925      	ldr	r1, [pc, #148]	; (8003024 <ae_setup_config+0x208>)
 8002f8e:	2300      	movs	r3, #0
 8002f90:	2220      	movs	r2, #32
 8002f92:	2001      	movs	r0, #1
 8002f94:	f7ff fce2 	bl	800295c <ae_write_data_slot>
 8002f98:	b3b0      	cbz	r0, 8003008 <ae_setup_config+0x1ec>
 8002f9a:	e00a      	b.n	8002fb2 <ae_setup_config+0x196>


            case KEYNUM_words: {
                    // - hmac key for phishing words (and then we forget it)
                    uint8_t     tmp[32];
                    rng_buffer(tmp, sizeof(tmp));
 8002f9c:	2120      	movs	r1, #32
 8002f9e:	a806      	add	r0, sp, #24
 8002fa0:	f7ff f842 	bl	8002028 <rng_buffer>

                    if(ae_write_data_slot(kn, tmp, 32, true)) {
 8002fa4:	2301      	movs	r3, #1
 8002fa6:	2220      	movs	r2, #32
 8002fa8:	a906      	add	r1, sp, #24
 8002faa:	2002      	movs	r0, #2
 8002fac:	f7ff fcd6 	bl	800295c <ae_write_data_slot>
 8002fb0:	b180      	cbz	r0, 8002fd4 <ae_setup_config+0x1b8>
                        INCONSISTENT("wr word");
 8002fb2:	481b      	ldr	r0, [pc, #108]	; (8003020 <ae_setup_config+0x204>)
 8002fb4:	f7fd fa0a 	bl	80003cc <fatal_error>
                    }
                }
                break;
 8002fb8:	e00c      	b.n	8002fd4 <ae_setup_config+0x1b8>
            case KEYNUM_pin_4:
            case KEYNUM_lastgood_1:
            case KEYNUM_lastgood_2:
            case KEYNUM_brickme:
            case KEYNUM_firmware:
                if(ae_write_data_slot(kn, zeros, 32, false)) {
 8002fba:	2300      	movs	r3, #0
 8002fbc:	2220      	movs	r2, #32
 8002fbe:	e001      	b.n	8002fc4 <ae_setup_config+0x1a8>

            case KEYNUM_secret_1:
            case KEYNUM_secret_2:
            case KEYNUM_secret_3:
            case KEYNUM_secret_4:
                if(ae_write_data_slot(kn, zeros, 72, false)) {
 8002fc0:	2300      	movs	r3, #0
 8002fc2:	2248      	movs	r2, #72	; 0x48
 8002fc4:	a90e      	add	r1, sp, #56	; 0x38
 8002fc6:	4620      	mov	r0, r4
 8002fc8:	e7f0      	b.n	8002fac <ae_setup_config+0x190>
                    INCONSISTENT("wr blk 72");
                }
                break;

            case 0:
                if(ae_write_data_slot(kn, (const uint8_t *)copyright_msg, 32, true)) {
 8002fca:	2301      	movs	r3, #1
 8002fcc:	2220      	movs	r2, #32
 8002fce:	4916      	ldr	r1, [pc, #88]	; (8003028 <ae_setup_config+0x20c>)
 8002fd0:	2000      	movs	r0, #0
 8002fd2:	e7df      	b.n	8002f94 <ae_setup_config+0x178>
    
    // will use zeros for all PIN codes, and secret starting values
    uint8_t     zeros[72];
    memset(zeros, 0, sizeof(zeros));

    for(int kn=0; kn<16; kn++) {
 8002fd4:	2d10      	cmp	r5, #16
 8002fd6:	462c      	mov	r4, r5
 8002fd8:	d1c9      	bne.n	8002f6e <ae_setup_config+0x152>
                break;
        }
    }

    // lock the data zone and effectively enter normal operation.
    ae_keep_alive();
 8002fda:	f7ff f9a5 	bl	8002328 <ae_keep_alive>
ae_lock_data_zone(void)
{
    // NOTE: I haven't been able to calc CRC right, so not using it.

    // do the lock: mode=1 (datazone) + 0x80 (no CRC check)
    int rv = ae_send(OP_Lock, 0x81, 0x0000);
 8002fde:	2200      	movs	r2, #0
 8002fe0:	2181      	movs	r1, #129	; 0x81
 8002fe2:	2017      	movs	r0, #23
 8002fe4:	f7ff fa58 	bl	8002498 <ae_send>
    RET_IF_BAD(rv);
 8002fe8:	b120      	cbz	r0, 8002ff4 <ae_setup_config+0x1d8>
    }

    // lock the data zone and effectively enter normal operation.
    ae_keep_alive();
    if(ae_lock_data_zone()) {
        INCONSISTENT("data lock");
 8002fea:	480d      	ldr	r0, [pc, #52]	; (8003020 <ae_setup_config+0x204>)
 8002fec:	f7fd f9ee 	bl	80003cc <fatal_error>
    }

    return 0;
 8002ff0:	2000      	movs	r0, #0
 8002ff2:	e00b      	b.n	800300c <ae_setup_config+0x1f0>

    // do the lock: mode=1 (datazone) + 0x80 (no CRC check)
    int rv = ae_send(OP_Lock, 0x81, 0x0000);
    RET_IF_BAD(rv);

    ae_delay(OP_Lock);
 8002ff4:	2017      	movs	r0, #23
 8002ff6:	f7ff fa61 	bl	80024bc <ae_delay>

    return ae_read1();
 8002ffa:	f7ff f99f 	bl	800233c <ae_read1>
        }
    }

    // lock the data zone and effectively enter normal operation.
    ae_keep_alive();
    if(ae_lock_data_zone()) {
 8002ffe:	2800      	cmp	r0, #0
 8003000:	d0f6      	beq.n	8002ff0 <ae_setup_config+0x1d4>
 8003002:	e7f2      	b.n	8002fea <ae_setup_config+0x1ce>
    }

    if(!check_equal(rom_secrets->ae_serial_number, serial, 9)) {
        // write failed?
        // we're already linked to a different chip? Write failed?
        return EPERM;
 8003004:	2001      	movs	r0, #1
 8003006:	e001      	b.n	800300c <ae_setup_config+0x1f0>
    
    // will use zeros for all PIN codes, and secret starting values
    uint8_t     zeros[72];
    memset(zeros, 0, sizeof(zeros));

    for(int kn=0; kn<16; kn++) {
 8003008:	462c      	mov	r4, r5
 800300a:	e7b0      	b.n	8002f6e <ae_setup_config+0x152>
    if(ae_lock_data_zone()) {
        INCONSISTENT("data lock");
    }

    return 0;
}
 800300c:	b041      	add	sp, #260	; 0x104
 800300e:	bd30      	pop	{r4, r5, pc}
 8003010:	08006960 	.word	0x08006960
 8003014:	08007840 	.word	0x08007840
 8003018:	0800727f 	.word	0x0800727f
 800301c:	080072f1 	.word	0x080072f1
 8003020:	08007230 	.word	0x08007230
 8003024:	08007800 	.word	0x08007800
 8003028:	080072c3 	.word	0x080072c3

0800302c <delay_ms>:
//
    void
delay_ms(int ms)
{
    // Clear the COUNTFLAG and reset value to zero
    SysTick->VAL = 0;
 800302c:	4b05      	ldr	r3, [pc, #20]	; (8003044 <delay_ms+0x18>)
 800302e:	2200      	movs	r2, #0
 8003030:	609a      	str	r2, [r3, #8]
    //SysTick->CTRL;  

    // Wait for ticks to happen
    while(ms > 0) {
 8003032:	2800      	cmp	r0, #0
 8003034:	dd05      	ble.n	8003042 <delay_ms+0x16>
        if(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
 8003036:	681a      	ldr	r2, [r3, #0]
 8003038:	03d2      	lsls	r2, r2, #15
            ms--;
 800303a:	bf48      	it	mi
 800303c:	f100 30ff 	addmi.w	r0, r0, #4294967295	; 0xffffffff
 8003040:	e7f7      	b.n	8003032 <delay_ms+0x6>
        }
    }
}
 8003042:	4770      	bx	lr
 8003044:	e000e010 	.word	0xe000e010

08003048 <delay_us>:
// delay_us()
//
    void
delay_us(int us)
{
    if(us > 1000) {
 8003048:	f5b0 7f7a 	cmp.w	r0, #1000	; 0x3e8

// delay_us()
//
    void
delay_us(int us)
{
 800304c:	b507      	push	{r0, r1, r2, lr}
    if(us > 1000) {
 800304e:	dd08      	ble.n	8003062 <delay_us+0x1a>
        // big round up
        delay_ms((us + 500) / 1000);
 8003050:	f44f 737a 	mov.w	r3, #1000	; 0x3e8
 8003054:	f500 70fa 	add.w	r0, r0, #500	; 0x1f4
 8003058:	fb90 f0f3 	sdiv	r0, r0, r3
 800305c:	f7ff ffe6 	bl	800302c <delay_ms>
 8003060:	e00c      	b.n	800307c <delay_us+0x34>

    } else {
        // XXX calibrate this
        for(volatile int i=0; i<(10000*us); i++) {
 8003062:	2300      	movs	r3, #0
 8003064:	9301      	str	r3, [sp, #4]
 8003066:	f242 7310 	movw	r3, #10000	; 0x2710
 800306a:	4358      	muls	r0, r3
 800306c:	9b01      	ldr	r3, [sp, #4]
 800306e:	4298      	cmp	r0, r3
 8003070:	dd04      	ble.n	800307c <delay_us+0x34>
 8003072:	bf00      	nop
 8003074:	9b01      	ldr	r3, [sp, #4]
 8003076:	3301      	adds	r3, #1
 8003078:	9301      	str	r3, [sp, #4]
 800307a:	e7f7      	b.n	800306c <delay_us+0x24>
            __NOP();
        }
    }
}
 800307c:	b003      	add	sp, #12
 800307e:	f85d fb04 	ldr.w	pc, [sp], #4
	...

08003084 <gpio_setup>:
    // NOTES:
    // - try not to limit PCB changes for future revs; leave unused unchanged.
    // - oled_setup() uses pins on PA6 thru PA8

    // enable clock to that part of chip
    __HAL_RCC_GPIOA_CLK_ENABLE();
 8003084:	4b16      	ldr	r3, [pc, #88]	; (80030e0 <gpio_setup+0x5c>)
            .Pull = GPIO_NOPULL,
            .Speed = GPIO_SPEED_FREQ_LOW,
            .Alternate = 0,
        };

        HAL_GPIO_Init(DFU_BTN_PORT, &setup);
 8003086:	4817      	ldr	r0, [pc, #92]	; (80030e4 <gpio_setup+0x60>)
    // NOTES:
    // - try not to limit PCB changes for future revs; leave unused unchanged.
    // - oled_setup() uses pins on PA6 thru PA8

    // enable clock to that part of chip
    __HAL_RCC_GPIOA_CLK_ENABLE();
 8003088:	6cda      	ldr	r2, [r3, #76]	; 0x4c
//
// set directions, lock critical ones, etc.
//
    void
gpio_setup(void)
{
 800308a:	b530      	push	{r4, r5, lr}
    // NOTES:
    // - try not to limit PCB changes for future revs; leave unused unchanged.
    // - oled_setup() uses pins on PA6 thru PA8

    // enable clock to that part of chip
    __HAL_RCC_GPIOA_CLK_ENABLE();
 800308c:	f042 0201 	orr.w	r2, r2, #1
 8003090:	64da      	str	r2, [r3, #76]	; 0x4c
 8003092:	6cda      	ldr	r2, [r3, #76]	; 0x4c

        HAL_GPIO_Init(DFU_BTN_PORT, &setup);
    }

    {   // Onewire bus pin used for ATECC508A comms
        GPIO_InitTypeDef setup = {
 8003094:	4d14      	ldr	r5, [pc, #80]	; (80030e8 <gpio_setup+0x64>)
//
// set directions, lock critical ones, etc.
//
    void
gpio_setup(void)
{
 8003096:	b089      	sub	sp, #36	; 0x24
    // NOTES:
    // - try not to limit PCB changes for future revs; leave unused unchanged.
    // - oled_setup() uses pins on PA6 thru PA8

    // enable clock to that part of chip
    __HAL_RCC_GPIOA_CLK_ENABLE();
 8003098:	f002 0201 	and.w	r2, r2, #1
 800309c:	9201      	str	r2, [sp, #4]
 800309e:	9a01      	ldr	r2, [sp, #4]
    __HAL_RCC_GPIOB_CLK_ENABLE();
 80030a0:	6cda      	ldr	r2, [r3, #76]	; 0x4c
 80030a2:	f042 0202 	orr.w	r2, r2, #2
 80030a6:	64da      	str	r2, [r3, #76]	; 0x4c
 80030a8:	6cdb      	ldr	r3, [r3, #76]	; 0x4c
 80030aa:	f003 0302 	and.w	r3, r3, #2
 80030ae:	9302      	str	r3, [sp, #8]
 80030b0:	9b02      	ldr	r3, [sp, #8]

    {   // DFU button
        GPIO_InitTypeDef setup = {
 80030b2:	f44f 7380 	mov.w	r3, #256	; 0x100
 80030b6:	9303      	str	r3, [sp, #12]
            .Pull = GPIO_NOPULL,
            .Speed = GPIO_SPEED_FREQ_LOW,
            .Alternate = 0,
        };

        HAL_GPIO_Init(DFU_BTN_PORT, &setup);
 80030b8:	a903      	add	r1, sp, #12
    // enable clock to that part of chip
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();

    {   // DFU button
        GPIO_InitTypeDef setup = {
 80030ba:	2300      	movs	r3, #0
 80030bc:	9304      	str	r3, [sp, #16]
 80030be:	9305      	str	r3, [sp, #20]
 80030c0:	9306      	str	r3, [sp, #24]
 80030c2:	9307      	str	r3, [sp, #28]
            .Pull = GPIO_NOPULL,
            .Speed = GPIO_SPEED_FREQ_LOW,
            .Alternate = 0,
        };

        HAL_GPIO_Init(DFU_BTN_PORT, &setup);
 80030c4:	f7fd fe78 	bl	8000db8 <HAL_GPIO_Init>
    }

    {   // Onewire bus pin used for ATECC508A comms
        GPIO_InitTypeDef setup = {
 80030c8:	cd0f      	ldmia	r5!, {r0, r1, r2, r3}
 80030ca:	ac03      	add	r4, sp, #12
 80030cc:	c40f      	stmia	r4!, {r0, r1, r2, r3}
 80030ce:	682b      	ldr	r3, [r5, #0]
 80030d0:	6023      	str	r3, [r4, #0]
            .Pull = GPIO_NOPULL,
            .Speed = GPIO_SPEED_FREQ_MEDIUM,
            .Alternate = GPIO_AF8_UART4,
        };

        HAL_GPIO_Init(ONEWIRE_PORT, &setup);
 80030d2:	a903      	add	r1, sp, #12
 80030d4:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
 80030d8:	f7fd fe6e 	bl	8000db8 <HAL_GPIO_Init>

    // elsewhere...
    //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1);
    //HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0);
#endif
}
 80030dc:	b009      	add	sp, #36	; 0x24
 80030de:	bd30      	pop	{r4, r5, pc}
 80030e0:	40021000 	.word	0x40021000
 80030e4:	48000400 	.word	0x48000400
 80030e8:	08007318 	.word	0x08007318

080030ec <dfu_button_pressed>:
//
// sample the DFU button
//
    bool
dfu_button_pressed(void)
{
 80030ec:	b508      	push	{r3, lr}
    return (HAL_GPIO_ReadPin(DFU_BTN_PORT, DFU_BTN_PIN) == GPIO_PIN_SET);
 80030ee:	f44f 7180 	mov.w	r1, #256	; 0x100
 80030f2:	4803      	ldr	r0, [pc, #12]	; (8003100 <dfu_button_pressed+0x14>)
 80030f4:	f7fd ffd8 	bl	80010a8 <HAL_GPIO_ReadPin>
}
 80030f8:	1e43      	subs	r3, r0, #1
 80030fa:	4258      	negs	r0, r3
 80030fc:	4158      	adcs	r0, r3
 80030fe:	bd08      	pop	{r3, pc}
 8003100:	48000400 	.word	0x48000400

08003104 <_hmac_attempt>:
//
// Maybe should be proper HMAC from fips std? Can be changed later.
//
    static void
_hmac_attempt(const pinAttempt_t *args, uint8_t result[32])
{
 8003104:	b530      	push	{r4, r5, lr}
 8003106:	b09d      	sub	sp, #116	; 0x74
 8003108:	4605      	mov	r5, r0
    extern uint8_t      reboot_seed_base[32];        // constant per-boot

	SHA256_CTX ctx;

    sha256_init(&ctx);
 800310a:	4668      	mov	r0, sp
//
// Maybe should be proper HMAC from fips std? Can be changed later.
//
    static void
_hmac_attempt(const pinAttempt_t *args, uint8_t result[32])
{
 800310c:	460c      	mov	r4, r1
    extern uint8_t      reboot_seed_base[32];        // constant per-boot

	SHA256_CTX ctx;

    sha256_init(&ctx);
 800310e:	f002 f94f 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, rom_secrets->pairing_secret, 32);
 8003112:	4668      	mov	r0, sp
 8003114:	2220      	movs	r2, #32
 8003116:	490f      	ldr	r1, [pc, #60]	; (8003154 <_hmac_attempt+0x50>)
 8003118:	f002 f974 	bl	8005404 <sha256_update>
    sha256_update(&ctx, reboot_seed_base, 32);
 800311c:	4668      	mov	r0, sp
 800311e:	2220      	movs	r2, #32
 8003120:	490d      	ldr	r1, [pc, #52]	; (8003158 <_hmac_attempt+0x54>)
 8003122:	f002 f96f 	bl	8005404 <sha256_update>
    sha256_update(&ctx, (uint8_t *)args, offsetof(pinAttempt_t, hmac));
 8003126:	2244      	movs	r2, #68	; 0x44
 8003128:	4629      	mov	r1, r5
 800312a:	4668      	mov	r0, sp
 800312c:	f002 f96a 	bl	8005404 <sha256_update>
    sha256_final(&ctx, result);
 8003130:	4621      	mov	r1, r4
 8003132:	4668      	mov	r0, sp
 8003134:	f002 f984 	bl	8005440 <sha256_final>

    // and a second-sha256 on that, just in case.
    sha256_init(&ctx);
 8003138:	4668      	mov	r0, sp
 800313a:	f002 f939 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, result, 32);
 800313e:	2220      	movs	r2, #32
 8003140:	4621      	mov	r1, r4
 8003142:	4668      	mov	r0, sp
 8003144:	f002 f95e 	bl	8005404 <sha256_update>
    sha256_final(&ctx, result);
 8003148:	4621      	mov	r1, r4
 800314a:	4668      	mov	r0, sp
 800314c:	f002 f978 	bl	8005440 <sha256_final>
}
 8003150:	b01d      	add	sp, #116	; 0x74
 8003152:	bd30      	pop	{r4, r5, pc}
 8003154:	08007800 	.word	0x08007800
 8003158:	10007c00 	.word	0x10007c00

0800315c <_sign_attempt>:
// Provide our "signature" validating struct contents as coming from us.
//
    static void
_sign_attempt(pinAttempt_t *args)
{
    args->magic_value = PA_MAGIC;
 800315c:	4601      	mov	r1, r0
 800315e:	4b02      	ldr	r3, [pc, #8]	; (8003168 <_sign_attempt+0xc>)
 8003160:	f841 3b44 	str.w	r3, [r1], #68

    _hmac_attempt(args, args->hmac);
 8003164:	f7ff bfce 	b.w	8003104 <_hmac_attempt>
 8003168:	2eaf6311 	.word	0x2eaf6311

0800316c <_validate_attempt>:

// _validate_attempt()
//
    static int
_validate_attempt(pinAttempt_t *args, bool first_time)
{
 800316c:	b530      	push	{r4, r5, lr}
 800316e:	4604      	mov	r4, r0
 8003170:	b089      	sub	sp, #36	; 0x24
    if(first_time) {
 8003172:	460d      	mov	r5, r1
 8003174:	b961      	cbnz	r1, 8003190 <_validate_attempt+0x24>
        // no hmac needed for setup call
    } else {
        // if hmac is defined, better be right.
        uint8_t     actual[32];

        _hmac_attempt(args, actual);
 8003176:	4669      	mov	r1, sp
 8003178:	f7ff ffc4 	bl	8003104 <_hmac_attempt>

        if(!check_equal(actual, args->hmac, 32)) {
 800317c:	2220      	movs	r2, #32
 800317e:	f104 0144 	add.w	r1, r4, #68	; 0x44
 8003182:	4668      	mov	r0, sp
 8003184:	f7fe ff00 	bl	8001f88 <check_equal>
 8003188:	b910      	cbnz	r0, 8003190 <_validate_attempt+0x24>
            // hmac is wrong?
            return EPIN_HMAC_FAIL;
 800318a:	f06f 0063 	mvn.w	r0, #99	; 0x63
 800318e:	e021      	b.n	80031d4 <_validate_attempt+0x68>
        }
    }

    // check fields.
    if(args->magic_value != PA_MAGIC) {
 8003190:	6823      	ldr	r3, [r4, #0]
 8003192:	4a11      	ldr	r2, [pc, #68]	; (80031d8 <_validate_attempt+0x6c>)
 8003194:	4293      	cmp	r3, r2
 8003196:	d001      	beq.n	800319c <_validate_attempt+0x30>
        if(first_time && args->magic_value == 0) {
 8003198:	b1bd      	cbz	r5, 80031ca <_validate_attempt+0x5e>
 800319a:	b9b3      	cbnz	r3, 80031ca <_validate_attempt+0x5e>
            return EPIN_BAD_MAGIC;
        }
    }

    // check fields
    if(args->pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR;
 800319c:	6aa3      	ldr	r3, [r4, #40]	; 0x28
 800319e:	2b20      	cmp	r3, #32
 80031a0:	dc16      	bgt.n	80031d0 <_validate_attempt+0x64>
    if(args->old_pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR;
 80031a2:	f8d4 3088 	ldr.w	r3, [r4, #136]	; 0x88
 80031a6:	2b20      	cmp	r3, #32
 80031a8:	dc12      	bgt.n	80031d0 <_validate_attempt+0x64>
    if(args->new_pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR;
 80031aa:	f8d4 30ac 	ldr.w	r3, [r4, #172]	; 0xac
 80031ae:	2b20      	cmp	r3, #32
 80031b0:	dc0e      	bgt.n	80031d0 <_validate_attempt+0x64>
    if((args->change_flags & CHANGE__MASK) != args->change_flags) return EPIN_RANGE_ERR;
 80031b2:	6e63      	ldr	r3, [r4, #100]	; 0x64
 80031b4:	f033 033f 	bics.w	r3, r3, #63	; 0x3f
 80031b8:	d10a      	bne.n	80031d0 <_validate_attempt+0x64>

    if((args->is_secondary & 0x1) != args->is_secondary) return EPIN_RANGE_ERR;
 80031ba:	6863      	ldr	r3, [r4, #4]
        
    return 0;
 80031bc:	f033 0301 	bics.w	r3, r3, #1
 80031c0:	bf14      	ite	ne
 80031c2:	f06f 0066 	mvnne.w	r0, #102	; 0x66
 80031c6:	2000      	moveq	r0, #0
 80031c8:	e004      	b.n	80031d4 <_validate_attempt+0x68>
    // check fields.
    if(args->magic_value != PA_MAGIC) {
        if(first_time && args->magic_value == 0) {
            // allow it if first time
        } else {
            return EPIN_BAD_MAGIC;
 80031ca:	f06f 0065 	mvn.w	r0, #101	; 0x65
 80031ce:	e001      	b.n	80031d4 <_validate_attempt+0x68>
        }
    }

    // check fields
    if(args->pin_len > MAX_PIN_LEN) return EPIN_RANGE_ERR;
 80031d0:	f06f 0066 	mvn.w	r0, #102	; 0x66
    if((args->change_flags & CHANGE__MASK) != args->change_flags) return EPIN_RANGE_ERR;

    if((args->is_secondary & 0x1) != args->is_secondary) return EPIN_RANGE_ERR;
        
    return 0;
}
 80031d4:	b009      	add	sp, #36	; 0x24
 80031d6:	bd30      	pop	{r4, r5, pc}
 80031d8:	2eaf6311 	.word	0x2eaf6311

080031dc <warmup_ae>:

// warmup_ae()
//
    static int
warmup_ae(void)
{
 80031dc:	b510      	push	{r4, lr}
    ae_setup();
 80031de:	f7ff f867 	bl	80022b0 <ae_setup>
 80031e2:	2405      	movs	r4, #5

    for(int retry=0; retry<5; retry++) {
        if(!ae_probe()) break;
 80031e4:	f7ff fb7c 	bl	80028e0 <ae_probe>
 80031e8:	b108      	cbz	r0, 80031ee <warmup_ae+0x12>
    static int
warmup_ae(void)
{
    ae_setup();

    for(int retry=0; retry<5; retry++) {
 80031ea:	3c01      	subs	r4, #1
 80031ec:	d1fa      	bne.n	80031e4 <warmup_ae+0x8>
        if(!ae_probe()) break;
    }

    if(ae_pair_unlock()) return -1;
 80031ee:	f7ff fab9 	bl	8002764 <ae_pair_unlock>
 80031f2:	3000      	adds	r0, #0
 80031f4:	bf18      	it	ne
 80031f6:	2001      	movne	r0, #1

    return 0;
}
 80031f8:	4240      	negs	r0, r0
 80031fa:	bd10      	pop	{r4, pc}

080031fc <pin_is_blank>:
//
// Is a specific PIN defined already? Not safe to expose this directly to callers!
//
    static bool
pin_is_blank(whichPin_t which)
{
 80031fc:	b510      	push	{r4, lr}
 80031fe:	b088      	sub	sp, #32
    int keynum = -1;

    switch(which) {
 8003200:	2804      	cmp	r0, #4
 8003202:	d80c      	bhi.n	800321e <pin_is_blank+0x22>
 8003204:	e8df f000 	tbb	[pc, r0]
 8003208:	07050311 	.word	0x07050311
 800320c:	09          	.byte	0x09
 800320d:	00          	.byte	0x00
        case PIN_primary:
            keynum = KEYNUM_pin_1;
            break;

        case PIN_secondary:
            keynum = KEYNUM_pin_2;
 800320e:	2404      	movs	r4, #4
 8003210:	e00c      	b.n	800322c <pin_is_blank+0x30>
            break;

        case PIN_primary_duress:
            keynum = KEYNUM_pin_3;
 8003212:	2407      	movs	r4, #7
            break;
 8003214:	e00a      	b.n	800322c <pin_is_blank+0x30>

        case PIN_secondary_duress:
            keynum = KEYNUM_pin_4;
 8003216:	2408      	movs	r4, #8
            break;
 8003218:	e008      	b.n	800322c <pin_is_blank+0x30>

        case PIN_brickme:
            keynum = KEYNUM_brickme;
 800321a:	240d      	movs	r4, #13
            break;
 800321c:	e006      	b.n	800322c <pin_is_blank+0x30>

        default:
            INCONSISTENT("kn");
 800321e:	480e      	ldr	r0, [pc, #56]	; (8003258 <pin_is_blank+0x5c>)
 8003220:	f7fd f8d4 	bl	80003cc <fatal_error>
// Is a specific PIN defined already? Not safe to expose this directly to callers!
//
    static bool
pin_is_blank(whichPin_t which)
{
    int keynum = -1;
 8003224:	f04f 34ff 	mov.w	r4, #4294967295	; 0xffffffff
 8003228:	e000      	b.n	800322c <pin_is_blank+0x30>

    switch(which) {
        case PIN_primary:
            keynum = KEYNUM_pin_1;
 800322a:	2403      	movs	r4, #3
        default:
            INCONSISTENT("kn");
    }

    uint8_t blank[32];
    memset(blank, 0, sizeof(blank));
 800322c:	2220      	movs	r2, #32
 800322e:	2100      	movs	r1, #0
 8003230:	4668      	mov	r0, sp
 8003232:	f003 fb5f 	bl	80068f4 <memset>

    ae_reset_chip();
 8003236:	f7ff f82d 	bl	8002294 <ae_reset_chip>
    ae_pair_unlock();
 800323a:	f7ff fa93 	bl	8002764 <ae_pair_unlock>

    // passing this check with zeros, means it was blank.
    int is_blank = (ae_checkmac(keynum, blank) == 0);
 800323e:	4669      	mov	r1, sp
 8003240:	b2e0      	uxtb	r0, r4
 8003242:	f7ff fa0b 	bl	800265c <ae_checkmac>
 8003246:	4604      	mov	r4, r0

    // CAUTION? We've unlocked something maybe, but it's blank, so...
    ae_reset_chip();
 8003248:	f7ff f824 	bl	8002294 <ae_reset_chip>

    return is_blank;
}
 800324c:	fab4 f084 	clz	r0, r4
 8003250:	0940      	lsrs	r0, r0, #5
 8003252:	b008      	add	sp, #32
 8003254:	bd10      	pop	{r4, pc}
 8003256:	bf00      	nop
 8003258:	08007230 	.word	0x08007230

0800325c <pin_hash>:
//
// Hash up a string of digits in 32-byte goodness.
//
    static void
pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose)
{
 800325c:	b570      	push	{r4, r5, r6, lr}
 800325e:	b09e      	sub	sp, #120	; 0x78
    ASSERT(pin_len <= MAX_PIN_LEN);
 8003260:	2920      	cmp	r1, #32
//
// Hash up a string of digits in 32-byte goodness.
//
    static void
pin_hash(const char *pin, int pin_len, uint8_t result[32], uint32_t purpose)
{
 8003262:	4606      	mov	r6, r0
 8003264:	460d      	mov	r5, r1
 8003266:	4614      	mov	r4, r2
 8003268:	9301      	str	r3, [sp, #4]
    ASSERT(pin_len <= MAX_PIN_LEN);
 800326a:	dd03      	ble.n	8003274 <pin_hash+0x18>
 800326c:	4817      	ldr	r0, [pc, #92]	; (80032cc <pin_hash+0x70>)
 800326e:	f7fd f8ad 	bl	80003cc <fatal_error>
 8003272:	e005      	b.n	8003280 <pin_hash+0x24>

    if(pin_len == 0) {
 8003274:	b921      	cbnz	r1, 8003280 <pin_hash+0x24>
        // zero-length PIN is considered the "blank" one: all zero
        memset(result, 0, 32);
 8003276:	2220      	movs	r2, #32
 8003278:	4620      	mov	r0, r4
 800327a:	f003 fb3b 	bl	80068f4 <memset>
 800327e:	e022      	b.n	80032c6 <pin_hash+0x6a>

        return;
    }

	SHA256_CTX ctx;
    sha256_init(&ctx);
 8003280:	a802      	add	r0, sp, #8
 8003282:	f002 f895 	bl	80053b0 <sha256_init>

    sha256_update(&ctx, rom_secrets->pairing_secret, 32);
 8003286:	2220      	movs	r2, #32
 8003288:	4911      	ldr	r1, [pc, #68]	; (80032d0 <pin_hash+0x74>)
 800328a:	a802      	add	r0, sp, #8
 800328c:	f002 f8ba 	bl	8005404 <sha256_update>
    sha256_update(&ctx, (uint8_t *)&purpose, 4);
 8003290:	2204      	movs	r2, #4
 8003292:	eb0d 0102 	add.w	r1, sp, r2
 8003296:	a802      	add	r0, sp, #8
 8003298:	f002 f8b4 	bl	8005404 <sha256_update>
    sha256_update(&ctx, (uint8_t *)pin, pin_len);
 800329c:	462a      	mov	r2, r5
 800329e:	4631      	mov	r1, r6
 80032a0:	a802      	add	r0, sp, #8
 80032a2:	f002 f8af 	bl	8005404 <sha256_update>

    sha256_final(&ctx, result);
 80032a6:	4621      	mov	r1, r4
 80032a8:	a802      	add	r0, sp, #8
 80032aa:	f002 f8c9 	bl	8005440 <sha256_final>

    // and a second-sha256 on that, just in case.
    sha256_init(&ctx);
 80032ae:	a802      	add	r0, sp, #8
 80032b0:	f002 f87e 	bl	80053b0 <sha256_init>
    sha256_update(&ctx, result, 32);
 80032b4:	4621      	mov	r1, r4
 80032b6:	a802      	add	r0, sp, #8
 80032b8:	2220      	movs	r2, #32
 80032ba:	f002 f8a3 	bl	8005404 <sha256_update>
    sha256_final(&ctx, result);
 80032be:	4621      	mov	r1, r4
 80032c0:	a802      	add	r0, sp, #8
 80032c2:	f002 f8bd 	bl	8005440 <sha256_final>
}
 80032c6:	b01e      	add	sp, #120	; 0x78
 80032c8:	bd70      	pop	{r4, r5, r6, pc}
 80032ca:	bf00      	nop
 80032cc:	08006960 	.word	0x08006960
 80032d0:	08007800 	.word	0x08007800

080032d4 <is_duress_pin>:

// is_duress_pin()
//
    static bool
is_duress_pin(bool is_secondary, const uint8_t digest[32], bool is_blank, int *pin_kn)
{
 80032d4:	b570      	push	{r4, r5, r6, lr}
 80032d6:	460e      	mov	r6, r1
 80032d8:	461d      	mov	r5, r3
    // duress PIN can never be blank; that means it wasn't set yet
    if(is_blank) return false;
 80032da:	b10a      	cbz	r2, 80032e0 <is_duress_pin+0xc>
 80032dc:	2000      	movs	r0, #0
 80032de:	bd70      	pop	{r4, r5, r6, pc}

    int kn = is_secondary ? KEYNUM_pin_4 : KEYNUM_pin_3;
 80032e0:	2800      	cmp	r0, #0
 80032e2:	bf14      	ite	ne
 80032e4:	2408      	movne	r4, #8
 80032e6:	2407      	moveq	r4, #7

    ae_reset_chip();
 80032e8:	f7fe ffd4 	bl	8002294 <ae_reset_chip>
    ae_pair_unlock();
 80032ec:	f7ff fa3a 	bl	8002764 <ae_pair_unlock>
    if(ae_checkmac(kn, digest) == 0) {
 80032f0:	4631      	mov	r1, r6
 80032f2:	4620      	mov	r0, r4
 80032f4:	f7ff f9b2 	bl	800265c <ae_checkmac>
 80032f8:	2800      	cmp	r0, #0
 80032fa:	d1ef      	bne.n	80032dc <is_duress_pin+0x8>
        *pin_kn = kn;
 80032fc:	602c      	str	r4, [r5, #0]

        return true;
 80032fe:	2001      	movs	r0, #1
    }

    return false;
}
 8003300:	bd70      	pop	{r4, r5, r6, pc}
	...

08003304 <maybe_brick_myself>:
// works, immediately destroy the pairing secret so that we become
// a useless brick.
//
    static int
maybe_brick_myself(const char *pin, int pin_len)
{
 8003304:	b510      	push	{r4, lr}
    uint8_t     digest[32];
    int         rv = 0;

    if(!pin_len) return 0;
 8003306:	460c      	mov	r4, r1
// works, immediately destroy the pairing secret so that we become
// a useless brick.
//
    static int
maybe_brick_myself(const char *pin, int pin_len)
{
 8003308:	b088      	sub	sp, #32
    uint8_t     digest[32];
    int         rv = 0;

    if(!pin_len) return 0;
 800330a:	b1a1      	cbz	r1, 8003336 <maybe_brick_myself+0x32>

    pin_hash(pin, pin_len, digest, PIN_PURPOSE_NORMAL);
 800330c:	4b0b      	ldr	r3, [pc, #44]	; (800333c <maybe_brick_myself+0x38>)
 800330e:	466a      	mov	r2, sp
 8003310:	f7ff ffa4 	bl	800325c <pin_hash>

    ae_reset_chip();
 8003314:	f7fe ffbe 	bl	8002294 <ae_reset_chip>

    ae_pair_unlock();
 8003318:	f7ff fa24 	bl	8002764 <ae_pair_unlock>

    if(ae_checkmac(KEYNUM_brickme, digest) == 0) {
 800331c:	4669      	mov	r1, sp
 800331e:	200d      	movs	r0, #13
 8003320:	f7ff f99c 	bl	800265c <ae_checkmac>
 8003324:	b920      	cbnz	r0, 8003330 <maybe_brick_myself+0x2c>
        // success... kinda: brick time.
        ae_destroy_key(KEYNUM_pairing);
 8003326:	2001      	movs	r0, #1
 8003328:	f7ff fd50 	bl	8002dcc <ae_destroy_key>

        rv = 1;
 800332c:	2401      	movs	r4, #1
 800332e:	e000      	b.n	8003332 <maybe_brick_myself+0x2e>
//
    static int
maybe_brick_myself(const char *pin, int pin_len)
{
    uint8_t     digest[32];
    int         rv = 0;
 8003330:	2400      	movs	r4, #0
        ae_destroy_key(KEYNUM_pairing);

        rv = 1;
    }

    ae_reset_chip();
 8003332:	f7fe ffaf 	bl	8002294 <ae_reset_chip>
maybe_brick_myself(const char *pin, int pin_len)
{
    uint8_t     digest[32];
    int         rv = 0;

    if(!pin_len) return 0;
 8003336:	4620      	mov	r0, r4
    }

    ae_reset_chip();

    return rv;
}
 8003338:	b008      	add	sp, #32
 800333a:	bd10      	pop	{r4, pc}
 800333c:	334d1858 	.word	0x334d1858

08003340 <lookup_secret_lastgood.constprop.5>:
// Map from PIN keynum to corresponding secret/last good counter.
//
    static void
lookup_secret_lastgood(int kn, int *secret_kn, int *lastgood_kn)
{
    switch(kn) {
 8003340:	3803      	subs	r0, #3
 8003342:	2805      	cmp	r0, #5
 8003344:	d814      	bhi.n	8003370 <lookup_secret_lastgood.constprop.5+0x30>
 8003346:	e8df f000 	tbb	[pc, r0]
 800334a:	0703      	.short	0x0703
 800334c:	0d0b1313 	.word	0x0d0b1313
        case KEYNUM_pin_1:
            *secret_kn = KEYNUM_secret_1;
 8003350:	2309      	movs	r3, #9
 8003352:	600b      	str	r3, [r1, #0]
            *lastgood_kn = KEYNUM_lastgood_1;
 8003354:	2305      	movs	r3, #5
 8003356:	e009      	b.n	800336c <lookup_secret_lastgood.constprop.5+0x2c>
            break;

        case KEYNUM_pin_2:
            *secret_kn = KEYNUM_secret_2;
 8003358:	230a      	movs	r3, #10
 800335a:	600b      	str	r3, [r1, #0]
            *lastgood_kn = KEYNUM_lastgood_2;
 800335c:	2306      	movs	r3, #6
 800335e:	e005      	b.n	800336c <lookup_secret_lastgood.constprop.5+0x2c>
            break;

        case KEYNUM_pin_3:
            *secret_kn = KEYNUM_secret_3;
 8003360:	230b      	movs	r3, #11
 8003362:	e000      	b.n	8003366 <lookup_secret_lastgood.constprop.5+0x26>
            *lastgood_kn = -1;
            break;

        case KEYNUM_pin_4:
            *secret_kn = KEYNUM_secret_4;
 8003364:	230c      	movs	r3, #12
 8003366:	600b      	str	r3, [r1, #0]
            *lastgood_kn = -1;
 8003368:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 800336c:	6013      	str	r3, [r2, #0]
 800336e:	4770      	bx	lr
            break;

        default:
            INCONSISTENT("kn");
 8003370:	4801      	ldr	r0, [pc, #4]	; (8003378 <lookup_secret_lastgood.constprop.5+0x38>)
 8003372:	f7fd b82b 	b.w	80003cc <fatal_error>
 8003376:	bf00      	nop
 8003378:	08007230 	.word	0x08007230

0800337c <pin_prefix_words>:
// - should be rate-limited (or liked to PIN code rate-limiting somehow)
// - hash generated here is shown plaintext on bus (for HMAC operation).
//
    int
pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result)
{
 800337c:	b530      	push	{r4, r5, lr}
 800337e:	b091      	sub	sp, #68	; 0x44
    uint8_t     tmp[32];
    uint8_t     digest[32];

    // hash it up real good
    pin_hash(pin_prefix, prefix_len, tmp, PIN_PURPOSE_WORDS);
 8003380:	4b18      	ldr	r3, [pc, #96]	; (80033e4 <pin_prefix_words+0x68>)
// - should be rate-limited (or liked to PIN code rate-limiting somehow)
// - hash generated here is shown plaintext on bus (for HMAC operation).
//
    int
pin_prefix_words(const char *pin_prefix, int prefix_len, uint32_t *result)
{
 8003382:	4615      	mov	r5, r2
    uint8_t     tmp[32];
    uint8_t     digest[32];

    // hash it up real good
    pin_hash(pin_prefix, prefix_len, tmp, PIN_PURPOSE_WORDS);
 8003384:	466a      	mov	r2, sp
 8003386:	f7ff ff69 	bl	800325c <pin_hash>

    // some very weak rate limiting...
    uint32_t count = backup_data_get(IDX_WORD_LOOKUPS_USED);
 800338a:	2000      	movs	r0, #0
 800338c:	f7fe fd88 	bl	8001ea0 <backup_data_get>
 8003390:	4604      	mov	r4, r0
    backup_data_set(IDX_WORD_LOOKUPS_USED, count+1);
 8003392:	1c41      	adds	r1, r0, #1
 8003394:	2000      	movs	r0, #0
 8003396:	f7fe fd93 	bl	8001ec0 <backup_data_set>

    if(count > 25) {
 800339a:	2c19      	cmp	r4, #25
 800339c:	d905      	bls.n	80033aa <pin_prefix_words+0x2e>
        // there is hacking. no human does this many.
        INCONSISTENT("prefix attempts");
 800339e:	4812      	ldr	r0, [pc, #72]	; (80033e8 <pin_prefix_words+0x6c>)
 80033a0:	f7fd f814 	bl	80003cc <fatal_error>
    }

    delay_ms((count < 10) ? 150 : 2500);
 80033a4:	f640 10c4 	movw	r0, #2500	; 0x9c4
 80033a8:	e004      	b.n	80033b4 <pin_prefix_words+0x38>
 80033aa:	2c0a      	cmp	r4, #10
 80033ac:	f640 10c4 	movw	r0, #2500	; 0x9c4
 80033b0:	bf38      	it	cc
 80033b2:	2096      	movcc	r0, #150	; 0x96
 80033b4:	f7ff fe3a 	bl	800302c <delay_ms>

    // bounce it off chip in HMAC mode, using dedicated key for that purpose.
    ae_setup();
 80033b8:	f7fe ff7a 	bl	80022b0 <ae_setup>
    ae_pair_unlock();
 80033bc:	f7ff f9d2 	bl	8002764 <ae_pair_unlock>
	int rv = ae_hmac32(KEYNUM_words, tmp, digest);
 80033c0:	aa08      	add	r2, sp, #32
 80033c2:	4669      	mov	r1, sp
 80033c4:	2002      	movs	r0, #2
 80033c6:	f7ff fa45 	bl	8002854 <ae_hmac32>
 80033ca:	4604      	mov	r4, r0
    ae_reset_chip();
 80033cc:	f7fe ff62 	bl	8002294 <ae_reset_chip>

	if(rv) return -1;
 80033d0:	b91c      	cbnz	r4, 80033da <pin_prefix_words+0x5e>

    memcpy(result, digest, 4);
 80033d2:	9808      	ldr	r0, [sp, #32]
 80033d4:	6028      	str	r0, [r5, #0]

    return 0;
 80033d6:	4620      	mov	r0, r4
 80033d8:	e001      	b.n	80033de <pin_prefix_words+0x62>
    ae_setup();
    ae_pair_unlock();
	int rv = ae_hmac32(KEYNUM_words, tmp, digest);
    ae_reset_chip();

	if(rv) return -1;
 80033da:	f04f 30ff 	mov.w	r0, #4294967295	; 0xffffffff

    memcpy(result, digest, 4);

    return 0;
}
 80033de:	b011      	add	sp, #68	; 0x44
 80033e0:	bd30      	pop	{r4, r5, pc}
 80033e2:	bf00      	nop
 80033e4:	2e6d6773 	.word	0x2e6d6773
 80033e8:	08007230 	.word	0x08007230

080033ec <_calc_delay_required>:

// _calc_delay_required()
//
    uint32_t
_calc_delay_required(int num_fails)
{
 80033ec:	2831      	cmp	r0, #49	; 0x31
 80033ee:	bf9a      	itte	ls
 80033f0:	4b02      	ldrls	r3, [pc, #8]	; (80033fc <_calc_delay_required+0x10>)
 80033f2:	f833 0010 	ldrhls.w	r0, [r3, r0, lsl #1]
 80033f6:	f44f 4061 	movhi.w	r0, #57600	; 0xe100
        case 20 ... 49:  return MINUTES(120);
        default:         return MINUTES(8*60);
    }
#undef SECONDS
#undef MINUTES
}
 80033fa:	4770      	bx	lr
 80033fc:	0800732c 	.word	0x0800732c

08003400 <pin_setup_attempt>:
// Get number of failed attempts on a PIN, since last success. Calculate
// required delay, and setup initial struct for later attempts.
//
    int
pin_setup_attempt(pinAttempt_t *args)
{
 8003400:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
    STATIC_ASSERT(sizeof(pinAttempt_t) == PIN_ATTEMPT_SIZE);

    int rv = _validate_attempt(args, true);
 8003404:	2101      	movs	r1, #1
// Get number of failed attempts on a PIN, since last success. Calculate
// required delay, and setup initial struct for later attempts.
//
    int
pin_setup_attempt(pinAttempt_t *args)
{
 8003406:	b08a      	sub	sp, #40	; 0x28
 8003408:	4604      	mov	r4, r0
    STATIC_ASSERT(sizeof(pinAttempt_t) == PIN_ATTEMPT_SIZE);

    int rv = _validate_attempt(args, true);
 800340a:	f7ff feaf 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 800340e:	4605      	mov	r5, r0
 8003410:	2800      	cmp	r0, #0
 8003412:	d171      	bne.n	80034f8 <pin_setup_attempt+0xf8>
    // but not allowed to test for those cases even existing.

    // wipe most of struct, keep only what we expect and want!
    int is_secondary = args->is_secondary;
    char    pin_copy[MAX_PIN_LEN];
    int     pin_len = args->pin_len;
 8003414:	6aa7      	ldr	r7, [r4, #40]	; 0x28
    // NOTE: Can only attempt primary and secondary pins. If it happens to
    // match duress or brickme pins, then perhaps something happens,
    // but not allowed to test for those cases even existing.

    // wipe most of struct, keep only what we expect and want!
    int is_secondary = args->is_secondary;
 8003416:	f8d4 8004 	ldr.w	r8, [r4, #4]
    char    pin_copy[MAX_PIN_LEN];
    int     pin_len = args->pin_len;
    memcpy(pin_copy, args->pin, pin_len);
 800341a:	f104 0608 	add.w	r6, r4, #8
 800341e:	463a      	mov	r2, r7
 8003420:	4631      	mov	r1, r6
 8003422:	a802      	add	r0, sp, #8
 8003424:	f003 fa40 	bl	80068a8 <memcpy>

    memset(args, 0, sizeof(pinAttempt_t));
 8003428:	22f8      	movs	r2, #248	; 0xf8
 800342a:	4629      	mov	r1, r5
 800342c:	4620      	mov	r0, r4
 800342e:	f003 fa61 	bl	80068f4 <memset>

    args->magic_value = PA_MAGIC;
 8003432:	4b33      	ldr	r3, [pc, #204]	; (8003500 <pin_setup_attempt+0x100>)
    args->is_secondary = is_secondary;
    args->pin_len = pin_len;
 8003434:	62a7      	str	r7, [r4, #40]	; 0x28
    memcpy(pin_copy, args->pin, pin_len);

    memset(args, 0, sizeof(pinAttempt_t));

    args->magic_value = PA_MAGIC;
    args->is_secondary = is_secondary;
 8003436:	e884 0108 	stmia.w	r4, {r3, r8}
    args->pin_len = pin_len;
    memcpy(args->pin, pin_copy, pin_len);
 800343a:	463a      	mov	r2, r7
 800343c:	a902      	add	r1, sp, #8
 800343e:	4630      	mov	r0, r6
 8003440:	f003 fa32 	bl	80068a8 <memcpy>

    // unlock the AE chip
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 8003444:	f7ff feca 	bl	80031dc <warmup_ae>
 8003448:	b110      	cbz	r0, 8003450 <pin_setup_attempt+0x50>
 800344a:	f06f 0568 	mvn.w	r5, #104	; 0x68
 800344e:	e053      	b.n	80034f8 <pin_setup_attempt+0xf8>

    if(args->pin_len) {
 8003450:	6aa1      	ldr	r1, [r4, #40]	; 0x28
 8003452:	b981      	cbnz	r1, 8003476 <pin_setup_attempt+0x76>
        if(maybe_brick_myself(args->pin, args->pin_len)) {
            return EPIN_I_AM_BRICK;
        }
    }

    uint32_t count = 0, last_good = 0;
 8003454:	2300      	movs	r3, #0
 8003456:	9300      	str	r3, [sp, #0]
    if(get_last_success(args->is_secondary, &count, &last_good)) {
 8003458:	6863      	ldr	r3, [r4, #4]
    int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1;

    uint32_t     tmp;

    // use first 32-bits only
    if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1;
 800345a:	2204      	movs	r2, #4
            return EPIN_I_AM_BRICK;
        }
    }

    uint32_t count = 0, last_good = 0;
    if(get_last_success(args->is_secondary, &count, &last_good)) {
 800345c:	2b00      	cmp	r3, #0
    int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1;

    uint32_t     tmp;

    // use first 32-bits only
    if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1;
 800345e:	eb0d 0102 	add.w	r1, sp, r2
 8003462:	bf15      	itete	ne
 8003464:	2006      	movne	r0, #6
 8003466:	2005      	moveq	r0, #5
            return EPIN_I_AM_BRICK;
        }
    }

    uint32_t count = 0, last_good = 0;
    if(get_last_success(args->is_secondary, &count, &last_good)) {
 8003468:	2501      	movne	r5, #1
 800346a:	2500      	moveq	r5, #0
    int kn = is_secondary ? KEYNUM_lastgood_2 : KEYNUM_lastgood_1;

    uint32_t     tmp;

    // use first 32-bits only
    if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1;
 800346c:	f7ff fbb4 	bl	8002bd8 <ae_read_data_slot>
 8003470:	4602      	mov	r2, r0
 8003472:	b130      	cbz	r0, 8003482 <pin_setup_attempt+0x82>
 8003474:	e00f      	b.n	8003496 <pin_setup_attempt+0x96>
    if(warmup_ae()) return EPIN_I_AM_BRICK;

    if(args->pin_len) {
        // Implement the brickme feature here, nice and early: Immediate brickage if
        // provided PIN matches that special PIN.
        if(maybe_brick_myself(args->pin, args->pin_len)) {
 8003476:	4630      	mov	r0, r6
 8003478:	f7ff ff44 	bl	8003304 <maybe_brick_myself>
 800347c:	2800      	cmp	r0, #0
 800347e:	d0e9      	beq.n	8003454 <pin_setup_attempt+0x54>
 8003480:	e7e3      	b.n	800344a <pin_setup_attempt+0x4a>
    // use first 32-bits only
    if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1;

    *lastgood = tmp;

    int rv = ae_get_counter(counter, is_secondary ? 1 : 0, false);
 8003482:	4629      	mov	r1, r5
 8003484:	4668      	mov	r0, sp
    uint32_t     tmp;

    // use first 32-bits only
    if(ae_read_data_slot(kn, (uint8_t *)&tmp, 4)) return -1;

    *lastgood = tmp;
 8003486:	9e01      	ldr	r6, [sp, #4]

    int rv = ae_get_counter(counter, is_secondary ? 1 : 0, false);
 8003488:	f7ff f9bd 	bl	8002806 <ae_get_counter>
    if(rv) return -1;
 800348c:	3000      	adds	r0, #0
 800348e:	bf18      	it	ne
 8003490:	2001      	movne	r0, #1
 8003492:	4245      	negs	r5, r0
            return EPIN_I_AM_BRICK;
        }
    }

    uint32_t count = 0, last_good = 0;
    if(get_last_success(args->is_secondary, &count, &last_good)) {
 8003494:	b125      	cbz	r5, 80034a0 <pin_setup_attempt+0xa0>
        ae_reset_chip();
 8003496:	f7fe fefd 	bl	8002294 <ae_reset_chip>

        return EPIN_AE_FAIL;
 800349a:	f06f 0569 	mvn.w	r5, #105	; 0x69
 800349e:	e02b      	b.n	80034f8 <pin_setup_attempt+0xf8>
    }

    ae_reset_chip();
 80034a0:	f7fe fef8 	bl	8002294 <ae_reset_chip>

    args->attempt_target = count+1;
 80034a4:	9b00      	ldr	r3, [sp, #0]

    if(last_good > count) {
 80034a6:	42b3      	cmp	r3, r6
        return EPIN_AE_FAIL;
    }

    ae_reset_chip();

    args->attempt_target = count+1;
 80034a8:	f103 0201 	add.w	r2, r3, #1

    if(last_good > count) {
        // huh? monkey business
        args->num_fails = 99;
 80034ac:	bf34      	ite	cc
 80034ae:	2363      	movcc	r3, #99	; 0x63
    } else {
        args->num_fails = count - last_good;
 80034b0:	1b9b      	subcs	r3, r3, r6
 80034b2:	6363      	str	r3, [r4, #52]	; 0x34
    }

    // has the duress pin (this wallet) been used this power cycle?
    uint32_t fake_lastgood = backup_data_get(args->is_secondary 
 80034b4:	6863      	ldr	r3, [r4, #4]
        return EPIN_AE_FAIL;
    }

    ae_reset_chip();

    args->attempt_target = count+1;
 80034b6:	63a2      	str	r2, [r4, #56]	; 0x38
    } else {
        args->num_fails = count - last_good;
    }

    // has the duress pin (this wallet) been used this power cycle?
    uint32_t fake_lastgood = backup_data_get(args->is_secondary 
 80034b8:	2b00      	cmp	r3, #0
 80034ba:	bf14      	ite	ne
 80034bc:	2002      	movne	r0, #2
 80034be:	2001      	moveq	r0, #1
 80034c0:	f7fe fcee 	bl	8001ea0 <backup_data_get>
                                        ? IDX_DURESS_LASTGOOD_2 : IDX_DURESS_LASTGOOD_1);
    if(fake_lastgood) {
 80034c4:	b108      	cbz	r0, 80034ca <pin_setup_attempt+0xca>
        // lie about # of failures, but keep the pin-rate limiting
        args->num_fails = 0;
 80034c6:	2300      	movs	r3, #0
 80034c8:	6363      	str	r3, [r4, #52]	; 0x34
    }

    args->delay_required = _calc_delay_required(args->num_fails);
 80034ca:	6b63      	ldr	r3, [r4, #52]	; 0x34
        // tell the caller that, so we can present as empty device.
    }
#endif

    // need to know if we are blank/unused device
    if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) {
 80034cc:	6860      	ldr	r0, [r4, #4]
 80034ce:	2b31      	cmp	r3, #49	; 0x31
 80034d0:	bf96      	itet	ls
 80034d2:	4a0c      	ldrls	r2, [pc, #48]	; (8003504 <pin_setup_attempt+0x104>)
    if(fake_lastgood) {
        // lie about # of failures, but keep the pin-rate limiting
        args->num_fails = 0;
    }

    args->delay_required = _calc_delay_required(args->num_fails);
 80034d4:	f44f 4361 	movhi.w	r3, #57600	; 0xe100
 80034d8:	f832 3013 	ldrhls.w	r3, [r2, r3, lsl #1]
 80034dc:	6323      	str	r3, [r4, #48]	; 0x30
    args->delay_achieved = 0;
 80034de:	2300      	movs	r3, #0
        // tell the caller that, so we can present as empty device.
    }
#endif

    // need to know if we are blank/unused device
    if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) {
 80034e0:	1ac0      	subs	r0, r0, r3
 80034e2:	bf18      	it	ne
 80034e4:	2001      	movne	r0, #1
        // lie about # of failures, but keep the pin-rate limiting
        args->num_fails = 0;
    }

    args->delay_required = _calc_delay_required(args->num_fails);
    args->delay_achieved = 0;
 80034e6:	62e3      	str	r3, [r4, #44]	; 0x2c
        // tell the caller that, so we can present as empty device.
    }
#endif

    // need to know if we are blank/unused device
    if(pin_is_blank(args->is_secondary ? PIN_secondary : PIN_primary)) {
 80034e8:	f7ff fe88 	bl	80031fc <pin_is_blank>
 80034ec:	b108      	cbz	r0, 80034f2 <pin_setup_attempt+0xf2>
        args->state_flags = PA_SUCCESSFUL | PA_IS_BLANK;
 80034ee:	2303      	movs	r3, #3
 80034f0:	63e3      	str	r3, [r4, #60]	; 0x3c
    }

    _sign_attempt(args);
 80034f2:	4620      	mov	r0, r4
 80034f4:	f7ff fe32 	bl	800315c <_sign_attempt>

    return 0;
}
 80034f8:	4628      	mov	r0, r5
 80034fa:	b00a      	add	sp, #40	; 0x28
 80034fc:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 8003500:	2eaf6311 	.word	0x2eaf6311
 8003504:	0800732c 	.word	0x0800732c

08003508 <pin_delay>:
//
// Delay for one time unit, and prove it. Doesn't check PIN value itself.
//
    int
pin_delay(pinAttempt_t *args)
{
 8003508:	b538      	push	{r3, r4, r5, lr}
    int rv = _validate_attempt(args, false);
 800350a:	2100      	movs	r1, #0
//
// Delay for one time unit, and prove it. Doesn't check PIN value itself.
//
    int
pin_delay(pinAttempt_t *args)
{
 800350c:	4604      	mov	r4, r0
    int rv = _validate_attempt(args, false);
 800350e:	f7ff fe2d 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 8003512:	4605      	mov	r5, r0
 8003514:	b958      	cbnz	r0, 800352e <pin_delay+0x26>

    // prevent any monkey business w/ systick rate
    systick_setup();
 8003516:	f7fe fa6d 	bl	80019f4 <systick_setup>

    delay_ms(500);
 800351a:	f44f 70fa 	mov.w	r0, #500	; 0x1f4
 800351e:	f7ff fd85 	bl	800302c <delay_ms>

    args->delay_achieved += 1;
 8003522:	6ae3      	ldr	r3, [r4, #44]	; 0x2c
 8003524:	3301      	adds	r3, #1
 8003526:	62e3      	str	r3, [r4, #44]	; 0x2c

    _sign_attempt(args);
 8003528:	4620      	mov	r0, r4
 800352a:	f7ff fe17 	bl	800315c <_sign_attempt>

    return 0;
}
 800352e:	4628      	mov	r0, r5
 8003530:	bd38      	pop	{r3, r4, r5, pc}
	...

08003534 <pin_login_attempt>:
//
// Do the PIN check, and return a value. Or fail.
//
    int
pin_login_attempt(pinAttempt_t *args)
{
 8003534:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
    int rv = _validate_attempt(args, false);
 8003538:	2100      	movs	r1, #0
//
// Do the PIN check, and return a value. Or fail.
//
    int
pin_login_attempt(pinAttempt_t *args)
{
 800353a:	b0a0      	sub	sp, #128	; 0x80
 800353c:	4604      	mov	r4, r0
    int rv = _validate_attempt(args, false);
 800353e:	f7ff fe15 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 8003542:	2800      	cmp	r0, #0
 8003544:	f040 80af 	bne.w	80036a6 <pin_login_attempt+0x172>

    // did they wait long enough?
    if(args->delay_achieved < args->delay_required) {
 8003548:	6ae2      	ldr	r2, [r4, #44]	; 0x2c
 800354a:	6b23      	ldr	r3, [r4, #48]	; 0x30
 800354c:	429a      	cmp	r2, r3
 800354e:	f0c0 80ac 	bcc.w	80036aa <pin_login_attempt+0x176>
        return EPIN_MUST_WAIT;
    }

    if(args->state_flags & PA_SUCCESSFUL) {
 8003552:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 8003554:	07da      	lsls	r2, r3, #31
 8003556:	f100 80ab 	bmi.w	80036b0 <pin_login_attempt+0x17c>
        // already worked, or is blank
        return EPIN_WRONG_SUCCESS;
    }

    // unlock the AE chip
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 800355a:	f7ff fe3f 	bl	80031dc <warmup_ae>
 800355e:	4605      	mov	r5, r0
 8003560:	2800      	cmp	r0, #0
 8003562:	f040 80a8 	bne.w	80036b6 <pin_login_attempt+0x182>

    int pin_kn = -1;
 8003566:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 800356a:	9302      	str	r3, [sp, #8]
    bool is_duress = false;

    // hash up the pin now.
    uint32_t new_count = ~0;
 800356c:	9303      	str	r3, [sp, #12]
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);
 800356e:	aa06      	add	r2, sp, #24
 8003570:	4b58      	ldr	r3, [pc, #352]	; (80036d4 <pin_login_attempt+0x1a0>)
 8003572:	6aa1      	ldr	r1, [r4, #40]	; 0x28
 8003574:	f104 0008 	add.w	r0, r4, #8
 8003578:	f7ff fe70 	bl	800325c <pin_hash>

    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
 800357c:	6aa2      	ldr	r2, [r4, #40]	; 0x28
 800357e:	6860      	ldr	r0, [r4, #4]
 8003580:	fab2 f282 	clz	r2, r2
 8003584:	3000      	adds	r0, #0
 8003586:	a906      	add	r1, sp, #24
 8003588:	ab02      	add	r3, sp, #8
 800358a:	ea4f 1252 	mov.w	r2, r2, lsr #5
 800358e:	bf18      	it	ne
 8003590:	2001      	movne	r0, #1
 8003592:	f7ff fe9f 	bl	80032d4 <is_duress_pin>
 8003596:	6861      	ldr	r1, [r4, #4]
 8003598:	b158      	cbz	r0, 80035b2 <pin_login_attempt+0x7e>
        // they gave the duress PIN for this wallet... try to continue w/o any indication
        is_duress = true;

        // record this!
        backup_data_set(args->is_secondary ? IDX_DURESS_LASTGOOD_2 : IDX_DURESS_LASTGOOD_1,
 800359a:	2900      	cmp	r1, #0
 800359c:	6ba1      	ldr	r1, [r4, #56]	; 0x38
 800359e:	bf18      	it	ne
 80035a0:	2002      	movne	r0, #2
 80035a2:	f101 0101 	add.w	r1, r1, #1
 80035a6:	bf08      	it	eq
 80035a8:	2001      	moveq	r0, #1
 80035aa:	f7fe fc89 	bl	8001ec0 <backup_data_set>
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);

    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
        // they gave the duress PIN for this wallet... try to continue w/o any indication
        is_duress = true;
 80035ae:	2601      	movs	r6, #1
 80035b0:	e01d      	b.n	80035ee <pin_login_attempt+0xba>
    } else {
        // Assume it's the real PIN, and register as an attempt on that.

        // Is this attempt for the right count? Also, increament it.

        rv = ae_get_counter(&new_count, args->is_secondary ? 1 : 0, true);
 80035b2:	3100      	adds	r1, #0
 80035b4:	bf18      	it	ne
 80035b6:	2101      	movne	r1, #1
 80035b8:	2201      	movs	r2, #1
 80035ba:	a803      	add	r0, sp, #12
 80035bc:	f7ff f923 	bl	8002806 <ae_get_counter>
        if(rv) return EPIN_AE_FAIL;
 80035c0:	2800      	cmp	r0, #0
 80035c2:	d17b      	bne.n	80036bc <pin_login_attempt+0x188>

        if(args->attempt_target != new_count) {
 80035c4:	6ba2      	ldr	r2, [r4, #56]	; 0x38
 80035c6:	9b03      	ldr	r3, [sp, #12]
 80035c8:	429a      	cmp	r2, r3
 80035ca:	d17a      	bne.n	80036c2 <pin_login_attempt+0x18e>
// Important that every code path leading here is rate-limited, and also incr the counter.
//
    static bool
is_real_pin(bool is_secondary, const uint8_t digest[32], bool is_blank, int *pin_kn)
{
    int kn = is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1;
 80035cc:	6863      	ldr	r3, [r4, #4]
 80035ce:	2b00      	cmp	r3, #0
 80035d0:	bf14      	ite	ne
 80035d2:	2604      	movne	r6, #4
 80035d4:	2603      	moveq	r6, #3

    ae_reset_chip();
 80035d6:	f7fe fe5d 	bl	8002294 <ae_reset_chip>
    ae_pair_unlock();
 80035da:	f7ff f8c3 	bl	8002764 <ae_pair_unlock>

    if(ae_checkmac(kn, digest) == 0) {
 80035de:	a906      	add	r1, sp, #24
 80035e0:	4630      	mov	r0, r6
 80035e2:	f7ff f83b 	bl	800265c <ae_checkmac>
 80035e6:	2800      	cmp	r0, #0
 80035e8:	d16e      	bne.n	80036c8 <pin_login_attempt+0x194>
        *pin_kn = kn;
 80035ea:	9602      	str	r6, [sp, #8]

    // unlock the AE chip
    if(warmup_ae()) return EPIN_I_AM_BRICK;

    int pin_kn = -1;
    bool is_duress = false;
 80035ec:	462e      	mov	r6, r5
    }

    // SUCCESS! "digest" holds a working value.

    // reset rate-limiting on word lookups
    backup_data_set(IDX_WORD_LOOKUPS_USED, 0);
 80035ee:	2100      	movs	r1, #0
 80035f0:	4608      	mov	r0, r1
 80035f2:	f7fe fc65 	bl	8001ec0 <backup_data_set>

    // ASIDE: even if they above was bypassed, the following code will
    // fail when it tries to read/update the corresponding slots in the 508a.

    int secret_kn = -1, lastgood_kn = -1;
 80035f6:	aa20      	add	r2, sp, #128	; 0x80
 80035f8:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 80035fc:	f842 3d6c 	str.w	r3, [r2, #-108]!
    lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn);
 8003600:	a904      	add	r1, sp, #16
 8003602:	9802      	ldr	r0, [sp, #8]
    backup_data_set(IDX_WORD_LOOKUPS_USED, 0);

    // ASIDE: even if they above was bypassed, the following code will
    // fail when it tries to read/update the corresponding slots in the 508a.

    int secret_kn = -1, lastgood_kn = -1;
 8003604:	9304      	str	r3, [sp, #16]
    lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn);
 8003606:	f7ff fe9b 	bl	8003340 <lookup_secret_lastgood.constprop.5>

    if(lastgood_kn != -1) {
 800360a:	9f05      	ldr	r7, [sp, #20]
 800360c:	1c7b      	adds	r3, r7, #1
 800360e:	d011      	beq.n	8003634 <pin_login_attempt+0x100>

        // update the "last good" counter
        uint32_t    tmp[32/4] = {0};
 8003610:	f04f 0820 	mov.w	r8, #32
 8003614:	4642      	mov	r2, r8
 8003616:	2100      	movs	r1, #0
 8003618:	a80e      	add	r0, sp, #56	; 0x38
 800361a:	f003 f96b 	bl	80068f4 <memset>
        tmp[0] = new_count;
 800361e:	9b03      	ldr	r3, [sp, #12]
 8003620:	930e      	str	r3, [sp, #56]	; 0x38

        rv = ae_encrypted_write(lastgood_kn, pin_kn, digest, (void *)tmp, 32);
 8003622:	f8cd 8000 	str.w	r8, [sp]
 8003626:	ab0e      	add	r3, sp, #56	; 0x38
 8003628:	aa06      	add	r2, sp, #24
 800362a:	9902      	ldr	r1, [sp, #8]
 800362c:	4638      	mov	r0, r7
 800362e:	f7ff fa49 	bl	8002ac4 <ae_encrypted_write>
        if(rv) {
 8003632:	b950      	cbnz	r0, 800364a <pin_login_attempt+0x116>
            return EPIN_AE_FAIL;
        }
    }

    // mark as success
    args->state_flags = PA_SUCCESSFUL;
 8003634:	2301      	movs	r3, #1
    // I used to always read the secret, since it's so hard to get to this point,
    // but now just indicating if zero or non-zero so that we don't contaminate the
    // caller w/ sensitive data that they may not want yet.
    {   uint8_t ts[AE_SECRET_LEN];

        rv = ae_encrypted_read(secret_kn, pin_kn, digest, ts, AE_SECRET_LEN);
 8003636:	2748      	movs	r7, #72	; 0x48
            return EPIN_AE_FAIL;
        }
    }

    // mark as success
    args->state_flags = PA_SUCCESSFUL;
 8003638:	63e3      	str	r3, [r4, #60]	; 0x3c
    // I used to always read the secret, since it's so hard to get to this point,
    // but now just indicating if zero or non-zero so that we don't contaminate the
    // caller w/ sensitive data that they may not want yet.
    {   uint8_t ts[AE_SECRET_LEN];

        rv = ae_encrypted_read(secret_kn, pin_kn, digest, ts, AE_SECRET_LEN);
 800363a:	9700      	str	r7, [sp, #0]
 800363c:	ab0e      	add	r3, sp, #56	; 0x38
 800363e:	aa06      	add	r2, sp, #24
 8003640:	9902      	ldr	r1, [sp, #8]
 8003642:	9804      	ldr	r0, [sp, #16]
 8003644:	f7ff fa06 	bl	8002a54 <ae_encrypted_read>
        if(rv) {
 8003648:	b110      	cbz	r0, 8003650 <pin_login_attempt+0x11c>
            ae_reset_chip();
 800364a:	f7fe fe23 	bl	8002294 <ae_reset_chip>
 800364e:	e035      	b.n	80036bc <pin_login_attempt+0x188>

            return EPIN_AE_FAIL;
        }
        ae_reset_chip();
 8003650:	f7fe fe20 	bl	8002294 <ae_reset_chip>

        if(check_all_zeros(ts, AE_SECRET_LEN)) {
 8003654:	4639      	mov	r1, r7
 8003656:	a80e      	add	r0, sp, #56	; 0x38
 8003658:	f7fe fc8a 	bl	8001f70 <check_all_zeros>
 800365c:	b118      	cbz	r0, 8003666 <pin_login_attempt+0x132>
            args->state_flags |= PA_ZERO_SECRET;
 800365e:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 8003660:	f043 0310 	orr.w	r3, r3, #16
 8003664:	63e3      	str	r3, [r4, #60]	; 0x3c
        }
    }


    // indicate what featurs already enabled/non-blank
    if(is_duress) {
 8003666:	b11e      	cbz	r6, 8003670 <pin_login_attempt+0x13c>
        // provide false answers to status of duress and brickme
        args->state_flags |= (PA_HAS_DURESS | PA_HAS_BRICKME);
 8003668:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 800366a:	f043 030c 	orr.w	r3, r3, #12
 800366e:	e012      	b.n	8003696 <pin_login_attempt+0x162>
    } else {
        // do we have duress password?
        if(!pin_is_blank(args->is_secondary ? PIN_secondary_duress : PIN_primary_duress)) {
 8003670:	6863      	ldr	r3, [r4, #4]
 8003672:	2b00      	cmp	r3, #0
 8003674:	bf14      	ite	ne
 8003676:	2003      	movne	r0, #3
 8003678:	2002      	moveq	r0, #2
 800367a:	f7ff fdbf 	bl	80031fc <pin_is_blank>
 800367e:	b918      	cbnz	r0, 8003688 <pin_login_attempt+0x154>
            args->state_flags |= PA_HAS_DURESS;
 8003680:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 8003682:	f043 0304 	orr.w	r3, r3, #4
 8003686:	63e3      	str	r3, [r4, #60]	; 0x3c
        }

        // do we have brickme set?
        if(!pin_is_blank(PIN_brickme)) {
 8003688:	2004      	movs	r0, #4
 800368a:	f7ff fdb7 	bl	80031fc <pin_is_blank>
 800368e:	b918      	cbnz	r0, 8003698 <pin_login_attempt+0x164>
            args->state_flags |= PA_HAS_BRICKME;
 8003690:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 8003692:	f043 0308 	orr.w	r3, r3, #8
 8003696:	63e3      	str	r3, [r4, #60]	; 0x3c
    }

    // I was thinking of maybe storing duress flag into private state,
    // but no real need. Preserve for future usage and make sure upper
    // layers preserve it.
    args->private_state = rng_sample();
 8003698:	f7fe fc86 	bl	8001fa8 <rng_sample>
 800369c:	6420      	str	r0, [r4, #64]	; 0x40

    _sign_attempt(args);
 800369e:	4620      	mov	r0, r4
 80036a0:	f7ff fd5c 	bl	800315c <_sign_attempt>

    return 0;
 80036a4:	e012      	b.n	80036cc <pin_login_attempt+0x198>
 80036a6:	4605      	mov	r5, r0
 80036a8:	e010      	b.n	80036cc <pin_login_attempt+0x198>
    int rv = _validate_attempt(args, false);
    if(rv) return rv;

    // did they wait long enough?
    if(args->delay_achieved < args->delay_required) {
        return EPIN_MUST_WAIT;
 80036aa:	f06f 056a 	mvn.w	r5, #106	; 0x6a
 80036ae:	e00d      	b.n	80036cc <pin_login_attempt+0x198>
    }

    if(args->state_flags & PA_SUCCESSFUL) {
        // already worked, or is blank
        return EPIN_WRONG_SUCCESS;
 80036b0:	f06f 056c 	mvn.w	r5, #108	; 0x6c
 80036b4:	e00a      	b.n	80036cc <pin_login_attempt+0x198>
    }

    // unlock the AE chip
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 80036b6:	f06f 0568 	mvn.w	r5, #104	; 0x68
 80036ba:	e007      	b.n	80036cc <pin_login_attempt+0x198>
        // Assume it's the real PIN, and register as an attempt on that.

        // Is this attempt for the right count? Also, increament it.

        rv = ae_get_counter(&new_count, args->is_secondary ? 1 : 0, true);
        if(rv) return EPIN_AE_FAIL;
 80036bc:	f06f 0569 	mvn.w	r5, #105	; 0x69
 80036c0:	e004      	b.n	80036cc <pin_login_attempt+0x198>

        if(args->attempt_target != new_count) {
            // they just cost themselves an attempt too! (only hackers would come here)
            return EPIN_OLD_ATTEMPT;
 80036c2:	f06f 056d 	mvn.w	r5, #109	; 0x6d
 80036c6:	e001      	b.n	80036cc <pin_login_attempt+0x198>
        }

        // try it out / and determine if we should proceed under duress
        if(!is_real_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
            // code is just wrong.
            return EPIN_AUTH_FAIL;
 80036c8:	f06f 056f 	mvn.w	r5, #111	; 0x6f
    args->private_state = rng_sample();

    _sign_attempt(args);

    return 0;
}
 80036cc:	4628      	mov	r0, r5
 80036ce:	b020      	add	sp, #128	; 0x80
 80036d0:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 80036d4:	334d1858 	.word	0x334d1858

080036d8 <pin_change>:
//
// Change the PIN and/or secrets (must also know the value, or it must be blank)
//
    int
pin_change(pinAttempt_t *args)
{
 80036d8:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 80036dc:	2100      	movs	r1, #0
//
// Change the PIN and/or secrets (must also know the value, or it must be blank)
//
    int
pin_change(pinAttempt_t *args)
{
 80036de:	b09d      	sub	sp, #116	; 0x74
 80036e0:	4604      	mov	r4, r0
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 80036e2:	f7ff fd43 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 80036e6:	2800      	cmp	r0, #0
 80036e8:	f040 80ef 	bne.w	80038ca <pin_change+0x1f2>

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
 80036ec:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 80036ee:	07d9      	lsls	r1, r3, #31
 80036f0:	f140 80ed 	bpl.w	80038ce <pin_change+0x1f6>
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
    }

    if(args->state_flags & PA_IS_BLANK) {
 80036f4:	079a      	lsls	r2, r3, #30
 80036f6:	d504      	bpl.n	8003702 <pin_change+0x2a>
        // if blank, must provide blank value
        if(args->pin_len) return EPIN_RANGE_ERR;
 80036f8:	6aa3      	ldr	r3, [r4, #40]	; 0x28
 80036fa:	b113      	cbz	r3, 8003702 <pin_change+0x2a>
 80036fc:	f06f 0566 	mvn.w	r5, #102	; 0x66
 8003700:	e0ed      	b.n	80038de <pin_change+0x206>
    }

    // Look at change flags.

    const uint32_t cf = args->change_flags;
 8003702:	6e67      	ldr	r7, [r4, #100]	; 0x64

    // must be here to do something.
    if(cf == 0) return EPIN_RANGE_ERR;
 8003704:	2f00      	cmp	r7, #0
 8003706:	d0f9      	beq.n	80036fc <pin_change+0x24>

    if(cf & CHANGE_BRICKME_PIN) {
 8003708:	f017 0804 	ands.w	r8, r7, #4
 800370c:	d006      	beq.n	800371c <pin_change+0x44>
        if(args->is_secondary) {
 800370e:	6863      	ldr	r3, [r4, #4]
 8003710:	2b00      	cmp	r3, #0
 8003712:	f040 80df 	bne.w	80038d4 <pin_change+0x1fc>
            // only main PIN holder can define brickme PIN
            return EPIN_PRIMARY_ONLY;
        }
        if(cf != CHANGE_BRICKME_PIN) {
 8003716:	2f04      	cmp	r7, #4
 8003718:	f040 80df 	bne.w	80038da <pin_change+0x202>
            // only pin can be changed, nothing else.
            return EPIN_BAD_REQUEST;
        }
    }
    if((cf & CHANGE_DURESS_SECRET) && (cf & CHANGE_SECRET)) {
 800371c:	f007 0918 	and.w	r9, r7, #24
 8003720:	f1b9 0f18 	cmp.w	r9, #24
 8003724:	f000 80d9 	beq.w	80038da <pin_change+0x202>
        // can't change two secrets at once.
        return EPIN_BAD_REQUEST;
    }

    if(cf & CHANGE_SECONDARY_WALLET_PIN) {
 8003728:	f017 0620 	ands.w	r6, r7, #32
 800372c:	d006      	beq.n	800373c <pin_change+0x64>
        if(args->is_secondary) {
 800372e:	6863      	ldr	r3, [r4, #4]
 8003730:	2b00      	cmp	r3, #0
 8003732:	f040 80d2 	bne.w	80038da <pin_change+0x202>
            // only main user uses this call 
            return EPIN_BAD_REQUEST;
        }
        if(cf != CHANGE_SECONDARY_WALLET_PIN) {
 8003736:	2f20      	cmp	r7, #32
 8003738:	f040 80cf 	bne.w	80038da <pin_change+0x202>
    // pin up to this point ... none of the others.
    // That's why we need old_pin fields.

    // hash it up real good
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);
 800373c:	4b6a      	ldr	r3, [pc, #424]	; (80038e8 <pin_change+0x210>)
 800373e:	6aa1      	ldr	r1, [r4, #40]	; 0x28
 8003740:	aa04      	add	r2, sp, #16
 8003742:	f104 0008 	add.w	r0, r4, #8
 8003746:	f7ff fd89 	bl	800325c <pin_hash>

    // unlock the AE chip
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 800374a:	f7ff fd47 	bl	80031dc <warmup_ae>
 800374e:	4605      	mov	r5, r0
 8003750:	b110      	cbz	r0, 8003758 <pin_change+0x80>
 8003752:	f06f 0568 	mvn.w	r5, #104	; 0x68
 8003756:	e0c2      	b.n	80038de <pin_change+0x206>
    // But if they try to change duress wallet PIN, we can't actually work.
    // Same for brickme PIN.

    // SO ... we need to know if they started w/ a duress wallet.

    int pin_kn = -1;
 8003758:	ab1c      	add	r3, sp, #112	; 0x70
 800375a:	f04f 32ff 	mov.w	r2, #4294967295	; 0xffffffff
 800375e:	f843 2d68 	str.w	r2, [r3, #-104]!
    bool is_duress = false;
    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
 8003762:	6860      	ldr	r0, [r4, #4]
 8003764:	6aa2      	ldr	r2, [r4, #40]	; 0x28
 8003766:	3000      	adds	r0, #0
 8003768:	fab2 f282 	clz	r2, r2
 800376c:	bf18      	it	ne
 800376e:	2001      	movne	r0, #1
 8003770:	0952      	lsrs	r2, r2, #5
 8003772:	a904      	add	r1, sp, #16
 8003774:	f7ff fdae 	bl	80032d4 <is_duress_pin>
 8003778:	b948      	cbnz	r0, 800378e <pin_change+0xb6>
        is_duress = true;
    } else {
        // no real need to re-prove PIN knowledge.
        // if they tricked us, doesn't matter as below the 580a validates it all again
        pin_kn = (args->is_secondary || (cf & CHANGE_SECONDARY_WALLET_PIN))
                        ? KEYNUM_pin_2 : KEYNUM_pin_1;
 800377a:	6863      	ldr	r3, [r4, #4]
 800377c:	b923      	cbnz	r3, 8003788 <pin_change+0xb0>
 800377e:	2e00      	cmp	r6, #0
 8003780:	bf0c      	ite	eq
 8003782:	2303      	moveq	r3, #3
 8003784:	2304      	movne	r3, #4
 8003786:	e000      	b.n	800378a <pin_change+0xb2>
 8003788:	2304      	movs	r3, #4
    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
        is_duress = true;
    } else {
        // no real need to re-prove PIN knowledge.
        // if they tricked us, doesn't matter as below the 580a validates it all again
        pin_kn = (args->is_secondary || (cf & CHANGE_SECONDARY_WALLET_PIN))
 800378a:	9302      	str	r3, [sp, #8]
 800378c:	e012      	b.n	80037b4 <pin_change+0xdc>

    if(is_duress) {
        // user is a thug.. limit what they can do

        // check for brickme pin on everything here.
        if(maybe_brick_myself(args->old_pin, args->old_pin_len)
 800378e:	f8d4 1088 	ldr.w	r1, [r4, #136]	; 0x88
 8003792:	f104 0068 	add.w	r0, r4, #104	; 0x68
 8003796:	f7ff fdb5 	bl	8003304 <maybe_brick_myself>
 800379a:	2800      	cmp	r0, #0
 800379c:	d1d9      	bne.n	8003752 <pin_change+0x7a>
                || maybe_brick_myself(args->new_pin, args->new_pin_len)
 800379e:	f8d4 10ac 	ldr.w	r1, [r4, #172]	; 0xac
 80037a2:	f104 008c 	add.w	r0, r4, #140	; 0x8c
 80037a6:	f7ff fdad 	bl	8003304 <maybe_brick_myself>
 80037aa:	2800      	cmp	r0, #0
 80037ac:	d1d1      	bne.n	8003752 <pin_change+0x7a>
        ) {
            return EPIN_I_AM_BRICK;
        }

        // - pretend they got the validating PIN wrong
        if((cf & (CHANGE_WALLET_PIN | CHANGE_SECRET)) != cf) {
 80037ae:	f037 0309 	bics.w	r3, r7, #9
 80037b2:	d129      	bne.n	8003808 <pin_change+0x130>

            return EPIN_OLD_AUTH_FAIL;
        }
    }

    if(cf & (CHANGE_WALLET_PIN | CHANGE_SECRET | CHANGE_SECONDARY_WALLET_PIN)) {
 80037b4:	f017 0f29 	tst.w	r7, #41	; 0x29
 80037b8:	d002      	beq.n	80037c0 <pin_change+0xe8>
        target_kn = pin_kn;
 80037ba:	f8dd 8008 	ldr.w	r8, [sp, #8]
 80037be:	e00f      	b.n	80037e0 <pin_change+0x108>
    } else if(cf & (CHANGE_DURESS_PIN | CHANGE_DURESS_SECRET)) {
 80037c0:	f017 0f12 	tst.w	r7, #18
 80037c4:	d007      	beq.n	80037d6 <pin_change+0xfe>
        target_kn = args->is_secondary ?  KEYNUM_pin_4 : KEYNUM_pin_3;
 80037c6:	6863      	ldr	r3, [r4, #4]
 80037c8:	2b00      	cmp	r3, #0
 80037ca:	bf14      	ite	ne
 80037cc:	f04f 0808 	movne.w	r8, #8
 80037d0:	f04f 0807 	moveq.w	r8, #7
 80037d4:	e004      	b.n	80037e0 <pin_change+0x108>
    } else if(cf & CHANGE_BRICKME_PIN) {
 80037d6:	f1b8 0f00 	cmp.w	r8, #0
 80037da:	d08f      	beq.n	80036fc <pin_change+0x24>
        target_kn = KEYNUM_brickme;
 80037dc:	f04f 080d 	mov.w	r8, #13
        return EPIN_RANGE_ERR;
    }

    // Determine the hash protecting the secret/pin to be changed.
    uint8_t target_digest[32]; 
    if((target_kn != pin_kn) || (cf & CHANGE_SECONDARY_WALLET_PIN)) {
 80037e0:	9b02      	ldr	r3, [sp, #8]
 80037e2:	4598      	cmp	r8, r3
 80037e4:	d100      	bne.n	80037e8 <pin_change+0x110>
 80037e6:	b1a6      	cbz	r6, 8003812 <pin_change+0x13a>
        pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL);
 80037e8:	f8d4 1088 	ldr.w	r1, [r4, #136]	; 0x88
 80037ec:	4b3e      	ldr	r3, [pc, #248]	; (80038e8 <pin_change+0x210>)
 80037ee:	aa0c      	add	r2, sp, #48	; 0x30
 80037f0:	f104 0068 	add.w	r0, r4, #104	; 0x68
 80037f4:	f7ff fd32 	bl	800325c <pin_hash>

        // Check the old pin is right.
        ae_pair_unlock();
 80037f8:	f7fe ffb4 	bl	8002764 <ae_pair_unlock>
        if(ae_checkmac(target_kn, target_digest)) {
 80037fc:	a90c      	add	r1, sp, #48	; 0x30
 80037fe:	fa5f f088 	uxtb.w	r0, r8
 8003802:	f7fe ff2b 	bl	800265c <ae_checkmac>
 8003806:	b170      	cbz	r0, 8003826 <pin_change+0x14e>
            return EPIN_I_AM_BRICK;
        }

        // - pretend they got the validating PIN wrong
        if((cf & (CHANGE_WALLET_PIN | CHANGE_SECRET)) != cf) {
            ae_reset_chip();
 8003808:	f7fe fd44 	bl	8002294 <ae_reset_chip>

            return EPIN_OLD_AUTH_FAIL;
 800380c:	f06f 0570 	mvn.w	r5, #112	; 0x70
 8003810:	e065      	b.n	80038de <pin_change+0x206>
            ae_reset_chip();

            return EPIN_OLD_AUTH_FAIL;
        }
    } else {
        memcpy(target_digest, digest, 32);
 8003812:	f10d 0e10 	add.w	lr, sp, #16
 8003816:	e8be 000f 	ldmia.w	lr!, {r0, r1, r2, r3}
 800381a:	ae0c      	add	r6, sp, #48	; 0x30
 800381c:	c60f      	stmia	r6!, {r0, r1, r2, r3}
 800381e:	e89e 000f 	ldmia.w	lr, {r0, r1, r2, r3}
 8003822:	e886 000f 	stmia.w	r6, {r0, r1, r2, r3}
    }

    // Record new PIN value.
    if(cf & (CHANGE_WALLET_PIN | CHANGE_DURESS_PIN 
 8003826:	f017 0f27 	tst.w	r7, #39	; 0x27
 800382a:	d01b      	beq.n	8003864 <pin_change+0x18c>
                | CHANGE_BRICKME_PIN | CHANGE_SECONDARY_WALLET_PIN)) {

        uint8_t new_digest[32]; 
        pin_hash(args->new_pin, args->new_pin_len, new_digest, PIN_PURPOSE_NORMAL);
 800382c:	4b2e      	ldr	r3, [pc, #184]	; (80038e8 <pin_change+0x210>)
 800382e:	f8d4 10ac 	ldr.w	r1, [r4, #172]	; 0xac
 8003832:	aa14      	add	r2, sp, #80	; 0x50
 8003834:	f104 008c 	add.w	r0, r4, #140	; 0x8c
 8003838:	f7ff fd10 	bl	800325c <pin_hash>

        if(ae_encrypted_write(target_kn, target_kn, target_digest, new_digest, 32)) {
 800383c:	2320      	movs	r3, #32
 800383e:	9300      	str	r3, [sp, #0]
 8003840:	aa0c      	add	r2, sp, #48	; 0x30
 8003842:	ab14      	add	r3, sp, #80	; 0x50
 8003844:	4641      	mov	r1, r8
 8003846:	4640      	mov	r0, r8
 8003848:	f7ff f93c 	bl	8002ac4 <ae_encrypted_write>
 800384c:	2800      	cmp	r0, #0
 800384e:	d137      	bne.n	80038c0 <pin_change+0x1e8>
            goto ae_fail;
        }

        memcpy(target_digest, new_digest, 32);
 8003850:	ae14      	add	r6, sp, #80	; 0x50
 8003852:	ce0f      	ldmia	r6!, {r0, r1, r2, r3}
 8003854:	f10d 0e30 	add.w	lr, sp, #48	; 0x30
 8003858:	e8ae 000f 	stmia.w	lr!, {r0, r1, r2, r3}
 800385c:	e896 000f 	ldmia.w	r6, {r0, r1, r2, r3}
 8003860:	e88e 000f 	stmia.w	lr, {r0, r1, r2, r3}
    }

    // Record new secret.
    // Note the digest might have just changed above.
    if(cf & (CHANGE_SECRET | CHANGE_DURESS_SECRET)) {
 8003864:	f1b9 0f00 	cmp.w	r9, #0
 8003868:	d027      	beq.n	80038ba <pin_change+0x1e2>
        int secret_kn = -1, lastgood_kn = -1;
 800386a:	aa1c      	add	r2, sp, #112	; 0x70
 800386c:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003870:	f842 3d20 	str.w	r3, [r2, #-32]!
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);
 8003874:	a903      	add	r1, sp, #12
 8003876:	4640      	mov	r0, r8

        if(ae_encrypted_write(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN)){
 8003878:	f104 06b0 	add.w	r6, r4, #176	; 0xb0
 800387c:	f04f 0948 	mov.w	r9, #72	; 0x48
    }

    // Record new secret.
    // Note the digest might have just changed above.
    if(cf & (CHANGE_SECRET | CHANGE_DURESS_SECRET)) {
        int secret_kn = -1, lastgood_kn = -1;
 8003880:	9303      	str	r3, [sp, #12]
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);
 8003882:	f7ff fd5d 	bl	8003340 <lookup_secret_lastgood.constprop.5>

        if(ae_encrypted_write(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN)){
 8003886:	f8cd 9000 	str.w	r9, [sp]
 800388a:	4633      	mov	r3, r6
 800388c:	aa0c      	add	r2, sp, #48	; 0x30
 800388e:	4641      	mov	r1, r8
 8003890:	9803      	ldr	r0, [sp, #12]
 8003892:	f7ff f917 	bl	8002ac4 <ae_encrypted_write>
 8003896:	b998      	cbnz	r0, 80038c0 <pin_change+0x1e8>
            goto ae_fail;
        }

        // update the zero-secret flag to be correct.
        if(cf & CHANGE_SECRET) {
 8003898:	073b      	lsls	r3, r7, #28
 800389a:	d50e      	bpl.n	80038ba <pin_change+0x1e2>
            if(check_all_zeros(args->secret, AE_SECRET_LEN)) {
 800389c:	4649      	mov	r1, r9
 800389e:	4630      	mov	r0, r6
 80038a0:	f7fe fb66 	bl	8001f70 <check_all_zeros>
 80038a4:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 80038a6:	b110      	cbz	r0, 80038ae <pin_change+0x1d6>
                args->state_flags |= PA_ZERO_SECRET;
 80038a8:	f043 0310 	orr.w	r3, r3, #16
 80038ac:	e001      	b.n	80038b2 <pin_change+0x1da>
            } else {
                args->state_flags &= ~PA_ZERO_SECRET;
 80038ae:	f023 0310 	bic.w	r3, r3, #16
 80038b2:	63e3      	str	r3, [r4, #60]	; 0x3c
            }
            _sign_attempt(args);
 80038b4:	4620      	mov	r0, r4
 80038b6:	f7ff fc51 	bl	800315c <_sign_attempt>
        }
    }

    ae_reset_chip();
 80038ba:	f7fe fceb 	bl	8002294 <ae_reset_chip>

    // NOTE: do **not** update args here, definately not with success or something! 

    return 0;
 80038be:	e00e      	b.n	80038de <pin_change+0x206>

ae_fail:
    ae_reset_chip();
 80038c0:	f7fe fce8 	bl	8002294 <ae_reset_chip>

    return EPIN_AE_FAIL;
 80038c4:	f06f 0569 	mvn.w	r5, #105	; 0x69
 80038c8:	e009      	b.n	80038de <pin_change+0x206>
 80038ca:	4605      	mov	r5, r0
 80038cc:	e007      	b.n	80038de <pin_change+0x206>
    int rv = _validate_attempt(args, false);
    if(rv) return rv;

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
 80038ce:	f06f 056c 	mvn.w	r5, #108	; 0x6c
 80038d2:	e004      	b.n	80038de <pin_change+0x206>
    if(cf == 0) return EPIN_RANGE_ERR;

    if(cf & CHANGE_BRICKME_PIN) {
        if(args->is_secondary) {
            // only main PIN holder can define brickme PIN
            return EPIN_PRIMARY_ONLY;
 80038d4:	f06f 0571 	mvn.w	r5, #113	; 0x71
 80038d8:	e001      	b.n	80038de <pin_change+0x206>
        }
        if(cf != CHANGE_BRICKME_PIN) {
            // only pin can be changed, nothing else.
            return EPIN_BAD_REQUEST;
 80038da:	f06f 0567 	mvn.w	r5, #103	; 0x67

ae_fail:
    ae_reset_chip();

    return EPIN_AE_FAIL;
}
 80038de:	4628      	mov	r0, r5
 80038e0:	b01d      	add	sp, #116	; 0x74
 80038e2:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}
 80038e6:	bf00      	nop
 80038e8:	334d1858 	.word	0x334d1858

080038ec <pin_fetch_secret>:
// To encourage not keeping the secret in memory, a way to fetch it after already
// have proven you know the PIN.
//
    int
pin_fetch_secret(pinAttempt_t *args)
{
 80038ec:	b530      	push	{r4, r5, lr}
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 80038ee:	2100      	movs	r1, #0
// To encourage not keeping the secret in memory, a way to fetch it after already
// have proven you know the PIN.
//
    int
pin_fetch_secret(pinAttempt_t *args)
{
 80038f0:	b097      	sub	sp, #92	; 0x5c
 80038f2:	4604      	mov	r4, r0
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 80038f4:	f7ff fc3a 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 80038f8:	2800      	cmp	r0, #0
 80038fa:	d179      	bne.n	80039f0 <pin_fetch_secret+0x104>

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
 80038fc:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 80038fe:	07da      	lsls	r2, r3, #31
 8003900:	d571      	bpl.n	80039e6 <pin_fetch_secret+0xfa>
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
    }

    // just in case? covered already by successful state_flags
    if(args->delay_achieved < args->delay_required) {
 8003902:	6ae2      	ldr	r2, [r4, #44]	; 0x2c
 8003904:	6b23      	ldr	r3, [r4, #48]	; 0x30
 8003906:	429a      	cmp	r2, r3
 8003908:	d370      	bcc.n	80039ec <pin_fetch_secret+0x100>
        return EPIN_MUST_WAIT;
    }

    // hash up the pin now.
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);
 800390a:	4b3a      	ldr	r3, [pc, #232]	; (80039f4 <pin_fetch_secret+0x108>)
 800390c:	6aa1      	ldr	r1, [r4, #40]	; 0x28
 800390e:	aa06      	add	r2, sp, #24
 8003910:	f104 0008 	add.w	r0, r4, #8
 8003914:	f7ff fca2 	bl	800325c <pin_hash>

    // try it out / and determine if we should proceed under duress
    int pin_kn = -1;
 8003918:	ab16      	add	r3, sp, #88	; 0x58
 800391a:	f04f 32ff 	mov.w	r2, #4294967295	; 0xffffffff
 800391e:	f843 2d4c 	str.w	r2, [r3, #-76]!
    bool is_duress = false;
    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
 8003922:	6860      	ldr	r0, [r4, #4]
 8003924:	6aa2      	ldr	r2, [r4, #40]	; 0x28
 8003926:	3000      	adds	r0, #0
 8003928:	fab2 f282 	clz	r2, r2
 800392c:	bf18      	it	ne
 800392e:	2001      	movne	r0, #1
 8003930:	0952      	lsrs	r2, r2, #5
 8003932:	a906      	add	r1, sp, #24
 8003934:	f7ff fcce 	bl	80032d4 <is_duress_pin>
 8003938:	b930      	cbnz	r0, 8003948 <pin_fetch_secret+0x5c>
        is_duress = true;
    } else {
        // no real need to re-prove PIN knowledge.
        // if they tricked us, doesn't matter as below the 580a validates it all again
        pin_kn = args->is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1;
 800393a:	6863      	ldr	r3, [r4, #4]
 800393c:	2b00      	cmp	r3, #0
 800393e:	bf14      	ite	ne
 8003940:	2304      	movne	r3, #4
 8003942:	2303      	moveq	r3, #3
 8003944:	9303      	str	r3, [sp, #12]
 8003946:	e000      	b.n	800394a <pin_fetch_secret+0x5e>

    // try it out / and determine if we should proceed under duress
    int pin_kn = -1;
    bool is_duress = false;
    if(is_duress_pin(args->is_secondary, digest, (args->pin_len == 0), &pin_kn)) {
        is_duress = true;
 8003948:	2001      	movs	r0, #1
        // no real need to re-prove PIN knowledge.
        // if they tricked us, doesn't matter as below the 580a validates it all again
        pin_kn = args->is_secondary ? KEYNUM_pin_2 : KEYNUM_pin_1;
    }

    if(args->change_flags & CHANGE_DURESS_SECRET) {
 800394a:	6e63      	ldr	r3, [r4, #100]	; 0x64
 800394c:	06db      	lsls	r3, r3, #27
 800394e:	d52c      	bpl.n	80039aa <pin_fetch_secret+0xbe>
        // let them know the duress secret, iff: they are logged into
        // corresponding primary pin (not duress) and they know the duress
        // pin as well.
        // LATER: this feature not being used since we only write the duress secret
        if(is_duress) return EPIN_AUTH_FAIL;
 8003950:	bb40      	cbnz	r0, 80039a4 <pin_fetch_secret+0xb8>

        int target_kn = args->is_secondary ?  KEYNUM_pin_4 : KEYNUM_pin_3;
 8003952:	6863      	ldr	r3, [r4, #4]

        uint8_t target_digest[32]; 
        pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL);
 8003954:	f8d4 1088 	ldr.w	r1, [r4, #136]	; 0x88
        // corresponding primary pin (not duress) and they know the duress
        // pin as well.
        // LATER: this feature not being used since we only write the duress secret
        if(is_duress) return EPIN_AUTH_FAIL;

        int target_kn = args->is_secondary ?  KEYNUM_pin_4 : KEYNUM_pin_3;
 8003958:	2b00      	cmp	r3, #0
 800395a:	bf14      	ite	ne
 800395c:	2508      	movne	r5, #8
 800395e:	2507      	moveq	r5, #7

        uint8_t target_digest[32]; 
        pin_hash(args->old_pin, args->old_pin_len, target_digest, PIN_PURPOSE_NORMAL);
 8003960:	4b24      	ldr	r3, [pc, #144]	; (80039f4 <pin_fetch_secret+0x108>)
 8003962:	aa0e      	add	r2, sp, #56	; 0x38
 8003964:	f104 0068 	add.w	r0, r4, #104	; 0x68
 8003968:	f7ff fc78 	bl	800325c <pin_hash>

        // Check the that pin is right (optional, but if wrong, encrypted read gives garb)
        ae_pair_unlock();
 800396c:	f7fe fefa 	bl	8002764 <ae_pair_unlock>
        if(ae_checkmac(target_kn, target_digest)) {
 8003970:	a90e      	add	r1, sp, #56	; 0x38
 8003972:	4628      	mov	r0, r5
 8003974:	f7fe fe72 	bl	800265c <ae_checkmac>
 8003978:	b110      	cbz	r0, 8003980 <pin_fetch_secret+0x94>
            // they got old PIN wrong, we won't be able to help them
            ae_reset_chip();
 800397a:	f7fe fc8b 	bl	8002294 <ae_reset_chip>

            return EPIN_AUTH_FAIL;
 800397e:	e011      	b.n	80039a4 <pin_fetch_secret+0xb8>
        }

        int secret_kn = -1, lastgood_kn = -1;
 8003980:	aa16      	add	r2, sp, #88	; 0x58
 8003982:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003986:	f842 3d44 	str.w	r3, [r2, #-68]!
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);
 800398a:	a904      	add	r1, sp, #16
 800398c:	4628      	mov	r0, r5
            ae_reset_chip();

            return EPIN_AUTH_FAIL;
        }

        int secret_kn = -1, lastgood_kn = -1;
 800398e:	9304      	str	r3, [sp, #16]
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);
 8003990:	f7ff fcd6 	bl	8003340 <lookup_secret_lastgood.constprop.5>

        rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN);
 8003994:	2348      	movs	r3, #72	; 0x48
 8003996:	9300      	str	r3, [sp, #0]
 8003998:	aa0e      	add	r2, sp, #56	; 0x38
 800399a:	f104 03b0 	add.w	r3, r4, #176	; 0xb0
 800399e:	4629      	mov	r1, r5
 80039a0:	9804      	ldr	r0, [sp, #16]
 80039a2:	e013      	b.n	80039cc <pin_fetch_secret+0xe0>
    if(args->change_flags & CHANGE_DURESS_SECRET) {
        // let them know the duress secret, iff: they are logged into
        // corresponding primary pin (not duress) and they know the duress
        // pin as well.
        // LATER: this feature not being used since we only write the duress secret
        if(is_duress) return EPIN_AUTH_FAIL;
 80039a4:	f06f 006f 	mvn.w	r0, #111	; 0x6f
 80039a8:	e022      	b.n	80039f0 <pin_fetch_secret+0x104>
        int secret_kn = -1, lastgood_kn = -1;
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);

        rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN);
    } else {
        int secret_kn = -1, lastgood_kn = -1;
 80039aa:	aa16      	add	r2, sp, #88	; 0x58
 80039ac:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 80039b0:	f842 3d20 	str.w	r3, [r2, #-32]!
        lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn);
 80039b4:	a905      	add	r1, sp, #20
 80039b6:	9803      	ldr	r0, [sp, #12]
        int secret_kn = -1, lastgood_kn = -1;
        lookup_secret_lastgood(target_kn, &secret_kn, &lastgood_kn);

        rv = ae_encrypted_read(secret_kn, target_kn, target_digest, args->secret, AE_SECRET_LEN);
    } else {
        int secret_kn = -1, lastgood_kn = -1;
 80039b8:	9305      	str	r3, [sp, #20]
        lookup_secret_lastgood(pin_kn, &secret_kn, &lastgood_kn);
 80039ba:	f7ff fcc1 	bl	8003340 <lookup_secret_lastgood.constprop.5>

        // read out the secret that corresponds to that pin
        rv = ae_encrypted_read(secret_kn, pin_kn, digest, args->secret, AE_SECRET_LEN);
 80039be:	2348      	movs	r3, #72	; 0x48
 80039c0:	9903      	ldr	r1, [sp, #12]
 80039c2:	9805      	ldr	r0, [sp, #20]
 80039c4:	9300      	str	r3, [sp, #0]
 80039c6:	aa06      	add	r2, sp, #24
 80039c8:	f104 03b0 	add.w	r3, r4, #176	; 0xb0
 80039cc:	f7ff f842 	bl	8002a54 <ae_encrypted_read>
 80039d0:	4604      	mov	r4, r0
    }

    if(rv) {
 80039d2:	b120      	cbz	r0, 80039de <pin_fetch_secret+0xf2>
        ae_reset_chip();
 80039d4:	f7fe fc5e 	bl	8002294 <ae_reset_chip>

        return EPIN_AE_FAIL;
 80039d8:	f06f 0069 	mvn.w	r0, #105	; 0x69
 80039dc:	e008      	b.n	80039f0 <pin_fetch_secret+0x104>
    }

    ae_reset_chip();
 80039de:	f7fe fc59 	bl	8002294 <ae_reset_chip>

    return 0;
 80039e2:	4620      	mov	r0, r4
 80039e4:	e004      	b.n	80039f0 <pin_fetch_secret+0x104>
    int rv = _validate_attempt(args, false);
    if(rv) return rv;

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
 80039e6:	f06f 006c 	mvn.w	r0, #108	; 0x6c
 80039ea:	e001      	b.n	80039f0 <pin_fetch_secret+0x104>
    }

    // just in case? covered already by successful state_flags
    if(args->delay_achieved < args->delay_required) {
        return EPIN_MUST_WAIT;
 80039ec:	f06f 006a 	mvn.w	r0, #106	; 0x6a
    }

    ae_reset_chip();

    return 0;
}
 80039f0:	b017      	add	sp, #92	; 0x5c
 80039f2:	bd30      	pop	{r4, r5, pc}
 80039f4:	334d1858 	.word	0x334d1858

080039f8 <pin_firmware_greenlight>:
//
// Record current flash checksum and make green light go on.
//
    int
pin_firmware_greenlight(pinAttempt_t *args)
{
 80039f8:	b510      	push	{r4, lr}
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 80039fa:	2100      	movs	r1, #0
//
// Record current flash checksum and make green light go on.
//
    int
pin_firmware_greenlight(pinAttempt_t *args)
{
 80039fc:	b09a      	sub	sp, #104	; 0x68
 80039fe:	4604      	mov	r4, r0
    // Validate args and signature
    int rv = _validate_attempt(args, false);
 8003a00:	f7ff fbb4 	bl	800316c <_validate_attempt>
    if(rv) return rv;
 8003a04:	bb50      	cbnz	r0, 8003a5c <pin_firmware_greenlight+0x64>

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
 8003a06:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 8003a08:	07db      	lsls	r3, r3, #31
 8003a0a:	d529      	bpl.n	8003a60 <pin_firmware_greenlight+0x68>
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
    }

    if(args->is_secondary) {
 8003a0c:	6863      	ldr	r3, [r4, #4]
 8003a0e:	bb53      	cbnz	r3, 8003a66 <pin_firmware_greenlight+0x6e>
        // only main PIN holder can do this
        return EPIN_PRIMARY_ONLY;
    }

    // just in case?
    if(args->delay_achieved < args->delay_required) {
 8003a10:	6ae2      	ldr	r2, [r4, #44]	; 0x2c
 8003a12:	6b23      	ldr	r3, [r4, #48]	; 0x30
 8003a14:	429a      	cmp	r2, r3
 8003a16:	d329      	bcc.n	8003a6c <pin_firmware_greenlight+0x74>
        return EPIN_MUST_WAIT;
    }

    // step 1: calc the value to use
    uint8_t fw_check[32], world_check[32];
    checksum_flash(fw_check, world_check);
 8003a18:	a90a      	add	r1, sp, #40	; 0x28
 8003a1a:	a802      	add	r0, sp, #8
 8003a1c:	f7fd fec0 	bl	80017a0 <checksum_flash>

    // re-calc correct PIN
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);
 8003a20:	6aa1      	ldr	r1, [r4, #40]	; 0x28
 8003a22:	4b16      	ldr	r3, [pc, #88]	; (8003a7c <pin_firmware_greenlight+0x84>)
 8003a24:	f104 0008 	add.w	r0, r4, #8
 8003a28:	aa12      	add	r2, sp, #72	; 0x48
 8003a2a:	f7ff fc17 	bl	800325c <pin_hash>

    // write it out to chip.
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 8003a2e:	f7ff fbd5 	bl	80031dc <warmup_ae>
 8003a32:	4604      	mov	r4, r0
 8003a34:	b9e8      	cbnz	r0, 8003a72 <pin_firmware_greenlight+0x7a>

    rv = ae_encrypted_write(KEYNUM_firmware, KEYNUM_pin_1, digest, world_check, 32);
 8003a36:	2320      	movs	r3, #32
 8003a38:	9300      	str	r3, [sp, #0]
 8003a3a:	aa12      	add	r2, sp, #72	; 0x48
 8003a3c:	ab0a      	add	r3, sp, #40	; 0x28
 8003a3e:	2103      	movs	r1, #3
 8003a40:	200e      	movs	r0, #14
 8003a42:	f7ff f83f 	bl	8002ac4 <ae_encrypted_write>
    if(rv) {
 8003a46:	b120      	cbz	r0, 8003a52 <pin_firmware_greenlight+0x5a>
        ae_reset_chip();
 8003a48:	f7fe fc24 	bl	8002294 <ae_reset_chip>

        return EPIN_AE_FAIL;
 8003a4c:	f06f 0469 	mvn.w	r4, #105	; 0x69
 8003a50:	e011      	b.n	8003a76 <pin_firmware_greenlight+0x7e>
    }

    // turn on light
    rv = ae_set_gpio_secure(world_check);
 8003a52:	a80a      	add	r0, sp, #40	; 0x28
 8003a54:	f7ff f96c 	bl	8002d30 <ae_set_gpio_secure>
    if(rv) {
 8003a58:	b168      	cbz	r0, 8003a76 <pin_firmware_greenlight+0x7e>
 8003a5a:	e7f5      	b.n	8003a48 <pin_firmware_greenlight+0x50>
 8003a5c:	4604      	mov	r4, r0
 8003a5e:	e00a      	b.n	8003a76 <pin_firmware_greenlight+0x7e>
    int rv = _validate_attempt(args, false);
    if(rv) return rv;

    if((args->state_flags & PA_SUCCESSFUL) != PA_SUCCESSFUL) {
        // must come here with a successful PIN login (so it's rate limited nicely)
        return EPIN_WRONG_SUCCESS;
 8003a60:	f06f 046c 	mvn.w	r4, #108	; 0x6c
 8003a64:	e007      	b.n	8003a76 <pin_firmware_greenlight+0x7e>
    }

    if(args->is_secondary) {
        // only main PIN holder can do this
        return EPIN_PRIMARY_ONLY;
 8003a66:	f06f 0471 	mvn.w	r4, #113	; 0x71
 8003a6a:	e004      	b.n	8003a76 <pin_firmware_greenlight+0x7e>
    }

    // just in case?
    if(args->delay_achieved < args->delay_required) {
        return EPIN_MUST_WAIT;
 8003a6c:	f06f 046a 	mvn.w	r4, #106	; 0x6a
 8003a70:	e001      	b.n	8003a76 <pin_firmware_greenlight+0x7e>
    // re-calc correct PIN
    uint8_t     digest[32];
    pin_hash(args->pin, args->pin_len, digest, PIN_PURPOSE_NORMAL);

    // write it out to chip.
    if(warmup_ae()) return EPIN_I_AM_BRICK;
 8003a72:	f06f 0468 	mvn.w	r4, #104	; 0x68

        return EPIN_AE_FAIL;
    }

    return 0;
}
 8003a76:	4620      	mov	r0, r4
 8003a78:	b01a      	add	sp, #104	; 0x68
 8003a7a:	bd10      	pop	{r4, pc}
 8003a7c:	334d1858 	.word	0x334d1858

08003a80 <sf_read>:

// sf_read_bytes()
//
    static HAL_StatusTypeDef
sf_read(uint32_t addr, int len, uint8_t *buf)
{
 8003a80:	b573      	push	{r0, r1, r4, r5, r6, lr}
    // send via SPI(1)
    uint8_t     pkt[5] = { CMD_FAST_READ,
 8003a82:	230b      	movs	r3, #11
 8003a84:	f88d 3000 	strb.w	r3, [sp]
 8003a88:	0c03      	lsrs	r3, r0, #16
 8003a8a:	f88d 3001 	strb.w	r3, [sp, #1]
 8003a8e:	f88d 0003 	strb.w	r0, [sp, #3]
 8003a92:	0a03      	lsrs	r3, r0, #8

// sf_read_bytes()
//
    static HAL_StatusTypeDef
sf_read(uint32_t addr, int len, uint8_t *buf)
{
 8003a94:	460e      	mov	r6, r1
    // send via SPI(1)
    uint8_t     pkt[5] = { CMD_FAST_READ,
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff,
                            0x0 };  // for fast-read case

    CS_LOW();
 8003a96:	4812      	ldr	r0, [pc, #72]	; (8003ae0 <sf_read+0x60>)
//
    static HAL_StatusTypeDef
sf_read(uint32_t addr, int len, uint8_t *buf)
{
    // send via SPI(1)
    uint8_t     pkt[5] = { CMD_FAST_READ,
 8003a98:	f88d 3002 	strb.w	r3, [sp, #2]
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff,
                            0x0 };  // for fast-read case

    CS_LOW();
 8003a9c:	f44f 7100 	mov.w	r1, #512	; 0x200

// sf_read_bytes()
//
    static HAL_StatusTypeDef
sf_read(uint32_t addr, int len, uint8_t *buf)
{
 8003aa0:	4615      	mov	r5, r2
    // send via SPI(1)
    uint8_t     pkt[5] = { CMD_FAST_READ,
 8003aa2:	2200      	movs	r2, #0
 8003aa4:	f88d 2004 	strb.w	r2, [sp, #4]
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff,
                            0x0 };  // for fast-read case

    CS_LOW();
 8003aa8:	f7fd fb04 	bl	80010b4 <HAL_GPIO_WritePin>

    HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, pkt, sizeof(pkt), HAL_MAX_DELAY);
 8003aac:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003ab0:	2205      	movs	r2, #5
 8003ab2:	4669      	mov	r1, sp
 8003ab4:	480b      	ldr	r0, [pc, #44]	; (8003ae4 <sf_read+0x64>)
 8003ab6:	f7fd fb88 	bl	80011ca <HAL_SPI_Transmit>
    if(rv == HAL_OK) {
 8003aba:	4604      	mov	r4, r0
 8003abc:	b938      	cbnz	r0, 8003ace <sf_read+0x4e>
        rv = HAL_SPI_Receive(&sf_spi_port, buf, len, HAL_MAX_DELAY);
 8003abe:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003ac2:	b2b2      	uxth	r2, r6
 8003ac4:	4629      	mov	r1, r5
 8003ac6:	4807      	ldr	r0, [pc, #28]	; (8003ae4 <sf_read+0x64>)
 8003ac8:	f7fd fd6d 	bl	80015a6 <HAL_SPI_Receive>
 8003acc:	4604      	mov	r4, r0
    }

    CS_HIGH();
 8003ace:	2201      	movs	r2, #1
 8003ad0:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003ad4:	4802      	ldr	r0, [pc, #8]	; (8003ae0 <sf_read+0x60>)
 8003ad6:	f7fd faed 	bl	80010b4 <HAL_GPIO_WritePin>

    return rv;
}
 8003ada:	4620      	mov	r0, r4
 8003adc:	b002      	add	sp, #8
 8003ade:	bd70      	pop	{r4, r5, r6, pc}
 8003ae0:	48000400 	.word	0x48000400
 8003ae4:	100062e0 	.word	0x100062e0

08003ae8 <sf_write.constprop.1>:
}

// sf_write()
//
    static HAL_StatusTypeDef
sf_write(uint32_t addr, int len, const uint8_t *buf)
 8003ae8:	b5f7      	push	{r0, r1, r2, r4, r5, r6, r7, lr}
// sf_write_enable()
//
    static HAL_StatusTypeDef
sf_write_enable(void)
{
    uint8_t pkt = CMD_WREN;
 8003aea:	ad02      	add	r5, sp, #8
 8003aec:	2306      	movs	r3, #6
 8003aee:	f805 3d04 	strb.w	r3, [r5, #-4]!

    CS_LOW();
 8003af2:	2200      	movs	r2, #0
}

// sf_write()
//
    static HAL_StatusTypeDef
sf_write(uint32_t addr, int len, const uint8_t *buf)
 8003af4:	4606      	mov	r6, r0
 8003af6:	460f      	mov	r7, r1
    static HAL_StatusTypeDef
sf_write_enable(void)
{
    uint8_t pkt = CMD_WREN;

    CS_LOW();
 8003af8:	4834      	ldr	r0, [pc, #208]	; (8003bcc <sf_write.constprop.1+0xe4>)
 8003afa:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003afe:	f7fd fad9 	bl	80010b4 <HAL_GPIO_WritePin>

    HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY);
 8003b02:	2201      	movs	r2, #1
 8003b04:	4629      	mov	r1, r5
 8003b06:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003b0a:	4831      	ldr	r0, [pc, #196]	; (8003bd0 <sf_write.constprop.1+0xe8>)
 8003b0c:	f7fd fb5d 	bl	80011ca <HAL_SPI_Transmit>

    CS_HIGH();
 8003b10:	2201      	movs	r2, #1
{
    uint8_t pkt = CMD_WREN;

    CS_LOW();

    HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY);
 8003b12:	4604      	mov	r4, r0

    CS_HIGH();
 8003b14:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003b18:	482c      	ldr	r0, [pc, #176]	; (8003bcc <sf_write.constprop.1+0xe4>)
 8003b1a:	f7fd facb 	bl	80010b4 <HAL_GPIO_WritePin>
    static HAL_StatusTypeDef
sf_write(uint32_t addr, int len, const uint8_t *buf)
{
    // enable writing
    HAL_StatusTypeDef rv = sf_write_enable();
    if(rv) return rv;
 8003b1e:	2c00      	cmp	r4, #0
 8003b20:	d151      	bne.n	8003bc6 <sf_write.constprop.1+0xde>

    // do a "PAGE Program" aka. write
    uint8_t     pkt[4] = { CMD_WRITE,
 8003b22:	2302      	movs	r3, #2
 8003b24:	f88d 3004 	strb.w	r3, [sp, #4]
 8003b28:	0c33      	lsrs	r3, r6, #16
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff 
                        };

    CS_LOW();
 8003b2a:	4622      	mov	r2, r4
    // enable writing
    HAL_StatusTypeDef rv = sf_write_enable();
    if(rv) return rv;

    // do a "PAGE Program" aka. write
    uint8_t     pkt[4] = { CMD_WRITE,
 8003b2c:	f88d 3005 	strb.w	r3, [sp, #5]
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff 
                        };

    CS_LOW();
 8003b30:	f44f 7100 	mov.w	r1, #512	; 0x200
    // enable writing
    HAL_StatusTypeDef rv = sf_write_enable();
    if(rv) return rv;

    // do a "PAGE Program" aka. write
    uint8_t     pkt[4] = { CMD_WRITE,
 8003b34:	0a33      	lsrs	r3, r6, #8
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff 
                        };

    CS_LOW();
 8003b36:	4825      	ldr	r0, [pc, #148]	; (8003bcc <sf_write.constprop.1+0xe4>)
    // enable writing
    HAL_StatusTypeDef rv = sf_write_enable();
    if(rv) return rv;

    // do a "PAGE Program" aka. write
    uint8_t     pkt[4] = { CMD_WRITE,
 8003b38:	f88d 3006 	strb.w	r3, [sp, #6]
 8003b3c:	f88d 6007 	strb.w	r6, [sp, #7]
                            (addr>>16) & 0xff, (addr >> 8) & 0xff, addr & 0xff 
                        };

    CS_LOW();
 8003b40:	f7fd fab8 	bl	80010b4 <HAL_GPIO_WritePin>

    rv = HAL_SPI_Transmit(&sf_spi_port, pkt, sizeof(pkt), HAL_MAX_DELAY);
 8003b44:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003b48:	2204      	movs	r2, #4
 8003b4a:	4629      	mov	r1, r5
 8003b4c:	4820      	ldr	r0, [pc, #128]	; (8003bd0 <sf_write.constprop.1+0xe8>)
 8003b4e:	f7fd fb3c 	bl	80011ca <HAL_SPI_Transmit>
    if(rv == HAL_OK) {
 8003b52:	4604      	mov	r4, r0
 8003b54:	b938      	cbnz	r0, 8003b66 <sf_write.constprop.1+0x7e>
        rv = HAL_SPI_Transmit(&sf_spi_port, (uint8_t *)buf, len, HAL_MAX_DELAY);
 8003b56:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003b5a:	2280      	movs	r2, #128	; 0x80
 8003b5c:	4639      	mov	r1, r7
 8003b5e:	481c      	ldr	r0, [pc, #112]	; (8003bd0 <sf_write.constprop.1+0xe8>)
 8003b60:	f7fd fb33 	bl	80011ca <HAL_SPI_Transmit>
 8003b64:	4604      	mov	r4, r0
    }

    CS_HIGH();
 8003b66:	2201      	movs	r2, #1
 8003b68:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003b6c:	4817      	ldr	r0, [pc, #92]	; (8003bcc <sf_write.constprop.1+0xe4>)
 8003b6e:	f7fd faa1 	bl	80010b4 <HAL_GPIO_WritePin>

    if(rv == HAL_OK) {
 8003b72:	bb44      	cbnz	r4, 8003bc6 <sf_write.constprop.1+0xde>
sf_wait_wip_done()
{
    // read RDSR (status register) and busy-wait until 
    // the write operation is done
    while(1) {
        uint8_t pkt = CMD_RDSR, stat = 0;
 8003b74:	2305      	movs	r3, #5
 8003b76:	2200      	movs	r2, #0

        CS_LOW();
 8003b78:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003b7c:	4813      	ldr	r0, [pc, #76]	; (8003bcc <sf_write.constprop.1+0xe4>)
sf_wait_wip_done()
{
    // read RDSR (status register) and busy-wait until 
    // the write operation is done
    while(1) {
        uint8_t pkt = CMD_RDSR, stat = 0;
 8003b7e:	f88d 3002 	strb.w	r3, [sp, #2]
 8003b82:	f88d 2003 	strb.w	r2, [sp, #3]

        CS_LOW();
 8003b86:	f7fd fa95 	bl	80010b4 <HAL_GPIO_WritePin>

        HAL_StatusTypeDef rv = HAL_SPI_Transmit(&sf_spi_port, &pkt, 1, HAL_MAX_DELAY);
 8003b8a:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003b8e:	2201      	movs	r2, #1
 8003b90:	f10d 0102 	add.w	r1, sp, #2
 8003b94:	480e      	ldr	r0, [pc, #56]	; (8003bd0 <sf_write.constprop.1+0xe8>)
 8003b96:	f7fd fb18 	bl	80011ca <HAL_SPI_Transmit>

        if(rv == HAL_OK) {
 8003b9a:	4604      	mov	r4, r0
 8003b9c:	b940      	cbnz	r0, 8003bb0 <sf_write.constprop.1+0xc8>
            rv = HAL_SPI_Receive(&sf_spi_port, &stat, 1, HAL_MAX_DELAY);
 8003b9e:	f04f 33ff 	mov.w	r3, #4294967295	; 0xffffffff
 8003ba2:	2201      	movs	r2, #1
 8003ba4:	f10d 0103 	add.w	r1, sp, #3
 8003ba8:	4809      	ldr	r0, [pc, #36]	; (8003bd0 <sf_write.constprop.1+0xe8>)
 8003baa:	f7fd fcfc 	bl	80015a6 <HAL_SPI_Receive>
 8003bae:	4604      	mov	r4, r0
        }

        CS_HIGH();
 8003bb0:	2201      	movs	r2, #1
 8003bb2:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003bb6:	4805      	ldr	r0, [pc, #20]	; (8003bcc <sf_write.constprop.1+0xe4>)
 8003bb8:	f7fd fa7c 	bl	80010b4 <HAL_GPIO_WritePin>

        if(rv != HAL_OK) return rv;
 8003bbc:	b91c      	cbnz	r4, 8003bc6 <sf_write.constprop.1+0xde>

        if(stat & 0x01) continue;
 8003bbe:	f89d 3003 	ldrb.w	r3, [sp, #3]
 8003bc2:	07db      	lsls	r3, r3, #31
 8003bc4:	d4d6      	bmi.n	8003b74 <sf_write.constprop.1+0x8c>
    static HAL_StatusTypeDef
sf_write(uint32_t addr, int len, const uint8_t *buf)
{
    // enable writing
    HAL_StatusTypeDef rv = sf_write_enable();
    if(rv) return rv;
 8003bc6:	4620      	mov	r0, r4
    if(rv == HAL_OK) {
        rv = sf_wait_wip_done();
    }

    return rv;
}
 8003bc8:	b003      	add	sp, #12
 8003bca:	bdf0      	pop	{r4, r5, r6, r7, pc}
 8003bcc:	48000400 	.word	0x48000400
 8003bd0:	100062e0 	.word	0x100062e0

08003bd4 <sf_setup>:
sf_setup(void)
{
    HAL_StatusTypeDef rv;

    // enable some internal clocks
    __HAL_RCC_GPIOB_CLK_ENABLE();
 8003bd4:	4b2d      	ldr	r3, [pc, #180]	; (8003c8c <sf_setup+0xb8>)
//
// Ok to call this lots.
//
    void
sf_setup(void)
{
 8003bd6:	b530      	push	{r4, r5, lr}
    HAL_StatusTypeDef rv;

    // enable some internal clocks
    __HAL_RCC_GPIOB_CLK_ENABLE();
 8003bd8:	6cda      	ldr	r2, [r3, #76]	; 0x4c
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_SPI2_CLK_ENABLE();

    // simple pins
    GPIO_InitTypeDef setup = {
 8003bda:	4d2d      	ldr	r5, [pc, #180]	; (8003c90 <sf_setup+0xbc>)
sf_setup(void)
{
    HAL_StatusTypeDef rv;

    // enable some internal clocks
    __HAL_RCC_GPIOB_CLK_ENABLE();
 8003bdc:	f042 0202 	orr.w	r2, r2, #2
 8003be0:	64da      	str	r2, [r3, #76]	; 0x4c
 8003be2:	6cda      	ldr	r2, [r3, #76]	; 0x4c
//
// Ok to call this lots.
//
    void
sf_setup(void)
{
 8003be4:	b089      	sub	sp, #36	; 0x24
    HAL_StatusTypeDef rv;

    // enable some internal clocks
    __HAL_RCC_GPIOB_CLK_ENABLE();
 8003be6:	f002 0202 	and.w	r2, r2, #2
 8003bea:	9200      	str	r2, [sp, #0]
 8003bec:	9a00      	ldr	r2, [sp, #0]
    __HAL_RCC_GPIOC_CLK_ENABLE();
 8003bee:	6cda      	ldr	r2, [r3, #76]	; 0x4c
 8003bf0:	f042 0204 	orr.w	r2, r2, #4
 8003bf4:	64da      	str	r2, [r3, #76]	; 0x4c
 8003bf6:	6cda      	ldr	r2, [r3, #76]	; 0x4c
 8003bf8:	f002 0204 	and.w	r2, r2, #4
 8003bfc:	9201      	str	r2, [sp, #4]
 8003bfe:	9a01      	ldr	r2, [sp, #4]
    __HAL_RCC_SPI2_CLK_ENABLE();
 8003c00:	6d9a      	ldr	r2, [r3, #88]	; 0x58
 8003c02:	f442 4280 	orr.w	r2, r2, #16384	; 0x4000
 8003c06:	659a      	str	r2, [r3, #88]	; 0x58
 8003c08:	6d9b      	ldr	r3, [r3, #88]	; 0x58
 8003c0a:	f403 4380 	and.w	r3, r3, #16384	; 0x4000
 8003c0e:	9302      	str	r3, [sp, #8]
 8003c10:	9b02      	ldr	r3, [sp, #8]

    // simple pins
    GPIO_InitTypeDef setup = {
 8003c12:	cd0f      	ldmia	r5!, {r0, r1, r2, r3}
 8003c14:	ac03      	add	r4, sp, #12
 8003c16:	c40f      	stmia	r4!, {r0, r1, r2, r3}
 8003c18:	682b      	ldr	r3, [r5, #0]
        .Mode = GPIO_MODE_OUTPUT_PP,
        .Pull = GPIO_NOPULL,
        .Speed = GPIO_SPEED_FREQ_MEDIUM,
        .Alternate = 0,
    };
    HAL_GPIO_Init(GPIOB, &setup);
 8003c1a:	481e      	ldr	r0, [pc, #120]	; (8003c94 <sf_setup+0xc0>)
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_SPI2_CLK_ENABLE();

    // simple pins
    GPIO_InitTypeDef setup = {
 8003c1c:	6023      	str	r3, [r4, #0]
        .Mode = GPIO_MODE_OUTPUT_PP,
        .Pull = GPIO_NOPULL,
        .Speed = GPIO_SPEED_FREQ_MEDIUM,
        .Alternate = 0,
    };
    HAL_GPIO_Init(GPIOB, &setup);
 8003c1e:	a903      	add	r1, sp, #12
 8003c20:	f7fd f8ca 	bl	8000db8 <HAL_GPIO_Init>

    // starting value: high
    HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1);
 8003c24:	2201      	movs	r2, #1
 8003c26:	f44f 7100 	mov.w	r1, #512	; 0x200
 8003c2a:	481a      	ldr	r0, [pc, #104]	; (8003c94 <sf_setup+0xc0>)
    HAL_GPIO_Init(GPIOB, &setup);

    setup.Pin = SF_SPI_MOSI | SF_SPI_MISO;
    HAL_GPIO_Init(GPIOC, &setup);

    memset(&sf_spi_port, 0, sizeof(sf_spi_port));
 8003c2c:	4c1a      	ldr	r4, [pc, #104]	; (8003c98 <sf_setup+0xc4>)
        .Alternate = 0,
    };
    HAL_GPIO_Init(GPIOB, &setup);

    // starting value: high
    HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1);
 8003c2e:	f7fd fa41 	bl	80010b4 <HAL_GPIO_WritePin>

    // SPI pins, on various ports
    setup.Pin = SF_SPI_SCK;
 8003c32:	f44f 6380 	mov.w	r3, #1024	; 0x400
 8003c36:	9303      	str	r3, [sp, #12]
    setup.Mode = GPIO_MODE_AF_PP;
 8003c38:	2302      	movs	r3, #2
 8003c3a:	9304      	str	r3, [sp, #16]
    setup.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &setup);
 8003c3c:	a903      	add	r1, sp, #12
    HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1);

    // SPI pins, on various ports
    setup.Pin = SF_SPI_SCK;
    setup.Mode = GPIO_MODE_AF_PP;
    setup.Alternate = GPIO_AF5_SPI2;
 8003c3e:	2305      	movs	r3, #5
    HAL_GPIO_Init(GPIOB, &setup);
 8003c40:	4814      	ldr	r0, [pc, #80]	; (8003c94 <sf_setup+0xc0>)
    HAL_GPIO_WritePin(GPIOB, SF_CS_PIN, 1);

    // SPI pins, on various ports
    setup.Pin = SF_SPI_SCK;
    setup.Mode = GPIO_MODE_AF_PP;
    setup.Alternate = GPIO_AF5_SPI2;
 8003c42:	9307      	str	r3, [sp, #28]
    HAL_GPIO_Init(GPIOB, &setup);
 8003c44:	f7fd f8b8 	bl	8000db8 <HAL_GPIO_Init>

    setup.Pin = SF_SPI_MOSI | SF_SPI_MISO;
 8003c48:	230c      	movs	r3, #12
    HAL_GPIO_Init(GPIOC, &setup);
 8003c4a:	eb0d 0103 	add.w	r1, sp, r3
 8003c4e:	4813      	ldr	r0, [pc, #76]	; (8003c9c <sf_setup+0xc8>)
    setup.Pin = SF_SPI_SCK;
    setup.Mode = GPIO_MODE_AF_PP;
    setup.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(GPIOB, &setup);

    setup.Pin = SF_SPI_MOSI | SF_SPI_MISO;
 8003c50:	9303      	str	r3, [sp, #12]
    HAL_GPIO_Init(GPIOC, &setup);
 8003c52:	f7fd f8b1 	bl	8000db8 <HAL_GPIO_Init>

    memset(&sf_spi_port, 0, sizeof(sf_spi_port));
 8003c56:	2264      	movs	r2, #100	; 0x64
 8003c58:	2100      	movs	r1, #0
 8003c5a:	4620      	mov	r0, r4
 8003c5c:	f002 fe4a 	bl	80068f4 <memset>

    sf_spi_port.Instance = SPI2;

    // see SPI_InitTypeDef
    sf_spi_port.Init.Mode = SPI_MODE_MASTER;
 8003c60:	4a0f      	ldr	r2, [pc, #60]	; (8003ca0 <sf_setup+0xcc>)
 8003c62:	f44f 7382 	mov.w	r3, #260	; 0x104
 8003c66:	e884 000c 	stmia.w	r4, {r2, r3}
    sf_spi_port.Init.Direction = SPI_DIRECTION_2LINES;
    sf_spi_port.Init.DataSize = SPI_DATASIZE_8BIT;
 8003c6a:	f44f 63e0 	mov.w	r3, #1792	; 0x700
 8003c6e:	60e3      	str	r3, [r4, #12]
    sf_spi_port.Init.CLKPolarity = SPI_POLARITY_LOW;
    sf_spi_port.Init.CLKPhase = SPI_PHASE_1EDGE;
    sf_spi_port.Init.NSS = SPI_NSS_SOFT;
 8003c70:	f44f 7300 	mov.w	r3, #512	; 0x200
 8003c74:	61a3      	str	r3, [r4, #24]
    sf_spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;    // conservative
    sf_spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB;
    sf_spi_port.Init.TIMode = SPI_TIMODE_DISABLED;
    sf_spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    rv = HAL_SPI_Init(&sf_spi_port);
 8003c76:	4620      	mov	r0, r4
    sf_spi_port.Init.Direction = SPI_DIRECTION_2LINES;
    sf_spi_port.Init.DataSize = SPI_DATASIZE_8BIT;
    sf_spi_port.Init.CLKPolarity = SPI_POLARITY_LOW;
    sf_spi_port.Init.CLKPhase = SPI_PHASE_1EDGE;
    sf_spi_port.Init.NSS = SPI_NSS_SOFT;
    sf_spi_port.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;    // conservative
 8003c78:	2318      	movs	r3, #24
 8003c7a:	61e3      	str	r3, [r4, #28]
    sf_spi_port.Init.FirstBit = SPI_FIRSTBIT_MSB;
    sf_spi_port.Init.TIMode = SPI_TIMODE_DISABLED;
    sf_spi_port.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;

    rv = HAL_SPI_Init(&sf_spi_port);
 8003c7c:	f7fd fa5e 	bl	800113c <HAL_SPI_Init>
    ASSERT(!rv);
 8003c80:	b110      	cbz	r0, 8003c88 <sf_setup+0xb4>
 8003c82:	4808      	ldr	r0, [pc, #32]	; (8003ca4 <sf_setup+0xd0>)
 8003c84:	f7fc fba2 	bl	80003cc <fatal_error>
}
 8003c88:	b009      	add	sp, #36	; 0x24
 8003c8a:	bd30      	pop	{r4, r5, pc}
 8003c8c:	40021000 	.word	0x40021000
 8003c90:	080073c0 	.word	0x080073c0
 8003c94:	48000400 	.word	0x48000400
 8003c98:	100062e0 	.word	0x100062e0
 8003c9c:	48000800 	.word	0x48000800
 8003ca0:	40003800 	.word	0x40003800
 8003ca4:	08006960 	.word	0x08006960

08003ca8 <sf_firmware_upgrade>:
//
// maybe upgrade to a firmware image found in sflash
//
    void
sf_firmware_upgrade(void)
{
 8003ca8:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
 8003cac:	f5ad 7d01 	sub.w	sp, sp, #516	; 0x204
    coldcardFirmwareHeader_t    hdr = {};
 8003cb0:	2280      	movs	r2, #128	; 0x80
 8003cb2:	2100      	movs	r1, #0
 8003cb4:	4668      	mov	r0, sp
 8003cb6:	f002 fe1d 	bl	80068f4 <memset>

    // simple: just read in right spot to see header.
    sf_setup();
 8003cba:	f7ff ff8b 	bl	8003bd4 <sf_setup>

    if(sf_read(FW_HEADER_OFFSET, sizeof(hdr), (void *)&hdr) != HAL_OK) {
 8003cbe:	466a      	mov	r2, sp
 8003cc0:	2180      	movs	r1, #128	; 0x80
 8003cc2:	f44f 507e 	mov.w	r0, #16256	; 0x3f80
 8003cc6:	f7ff fedb 	bl	8003a80 <sf_read>
 8003cca:	4604      	mov	r4, r0
 8003ccc:	2800      	cmp	r0, #0
 8003cce:	f040 8094 	bne.w	8003dfa <sf_firmware_upgrade+0x152>
        // hardware issues, keep going
        return;
    }

    if(!verify_header(&hdr)) {
 8003cd2:	4668      	mov	r0, sp
 8003cd4:	f7fd fe34 	bl	8001940 <verify_header>
 8003cd8:	2800      	cmp	r0, #0
 8003cda:	f000 808e 	beq.w	8003dfa <sf_firmware_upgrade+0x152>
    //
    // Solution: Look for a duplicated header at end of file. Will always write that last,
    // and even do a checksum over the data in the sflash before writing final header it out.
    uint32_t off = hdr.firmware_length;

    coldcardFirmwareHeader_t    hdr2 = {};
 8003cde:	2280      	movs	r2, #128	; 0x80
    // during the 'upload' process, after first part written, but before you get to the
    // end, we'd be left in DFU-only for recover. Seems really likely to happen.
    //
    // Solution: Look for a duplicated header at end of file. Will always write that last,
    // and even do a checksum over the data in the sflash before writing final header it out.
    uint32_t off = hdr.firmware_length;
 8003ce0:	9f06      	ldr	r7, [sp, #24]

    coldcardFirmwareHeader_t    hdr2 = {};
 8003ce2:	4621      	mov	r1, r4
 8003ce4:	eb0d 0002 	add.w	r0, sp, r2
 8003ce8:	f002 fe04 	bl	80068f4 <memset>
    if(sf_read(off, sizeof(hdr2), (void *)&hdr2) != HAL_OK) {
 8003cec:	aa20      	add	r2, sp, #128	; 0x80
 8003cee:	2180      	movs	r1, #128	; 0x80
 8003cf0:	4638      	mov	r0, r7
 8003cf2:	f7ff fec5 	bl	8003a80 <sf_read>
 8003cf6:	2800      	cmp	r0, #0
 8003cf8:	d17f      	bne.n	8003dfa <sf_firmware_upgrade+0x152>
        // Huh??? 
        return;
    }

    if(memcmp(&hdr, &hdr2, sizeof(hdr)) != 0) {
 8003cfa:	2280      	movs	r2, #128	; 0x80
 8003cfc:	eb0d 0102 	add.w	r1, sp, r2
 8003d00:	4668      	mov	r0, sp
 8003d02:	f002 fdc2 	bl	800688a <memcmp>
 8003d06:	4604      	mov	r4, r0
 8003d08:	2800      	cmp	r0, #0
 8003d0a:	d176      	bne.n	8003dfa <sf_firmware_upgrade+0x152>
    //
    // LATER: if they unplug power part way thru, they land in fully-bricked mode,
    // even tho we have enough data (from SPI) to complete upgrade successfully.

    // Check for downgrade attack: show warning and stop.
    if(check_is_downgrade(hdr.timestamp)) {
 8003d0c:	a801      	add	r0, sp, #4
 8003d0e:	f7fd fdf9 	bl	8001904 <check_is_downgrade>
 8003d12:	b168      	cbz	r0, 8003d30 <sf_firmware_upgrade+0x88>
        oled_show(screen_downgrade);
 8003d14:	483b      	ldr	r0, [pc, #236]	; (8003e04 <sf_firmware_upgrade+0x15c>)
 8003d16:	f7fc ff8f 	bl	8000c38 <oled_show>

        // prevent second attempts.
        uint8_t zeros[128] = { 0 };
 8003d1a:	4621      	mov	r1, r4
 8003d1c:	2280      	movs	r2, #128	; 0x80
 8003d1e:	a840      	add	r0, sp, #256	; 0x100
 8003d20:	f002 fde8 	bl	80068f4 <memset>
        sf_write(off, sizeof(zeros), zeros);
 8003d24:	a940      	add	r1, sp, #256	; 0x100
 8003d26:	4638      	mov	r0, r7
 8003d28:	f7ff fede 	bl	8003ae8 <sf_write.constprop.1>
  \brief   Wait For Interrupt
  \details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
 */
__attribute__((always_inline)) __STATIC_INLINE void __WFI(void)
{
  __ASM volatile ("wfi");
 8003d2c:	bf30      	wfi
 8003d2e:	e7fd      	b.n	8003d2c <sf_firmware_upgrade+0x84>

        LOCKUP_FOREVER();
    }

    // Start the upgrade ... takes about a minute.
    sf_do_upgrade(hdr.firmware_length);
 8003d30:	f8dd 8018 	ldr.w	r8, [sp, #24]
// Copy from SPI flash to real flash, at final executable location.
//
    static void
sf_do_upgrade(uint32_t size)
{
    ASSERT(size >= FW_MIN_LENGTH);
 8003d34:	f5b8 2f80 	cmp.w	r8, #262144	; 0x40000
 8003d38:	d202      	bcs.n	8003d40 <sf_firmware_upgrade+0x98>
 8003d3a:	4833      	ldr	r0, [pc, #204]	; (8003e08 <sf_firmware_upgrade+0x160>)
 8003d3c:	f7fc fb46 	bl	80003cc <fatal_error>

    flash_setup0();
 8003d40:	f7fd ff34 	bl	8001bac <flash_setup0>

    flash_unlock();
 8003d44:	f7fd ff56 	bl	8001bf4 <flash_unlock>

    uint8_t     tmp[256] __attribute__((aligned(8)));

    for(uint32_t pos=0; pos<size; pos += sizeof(tmp)) {
 8003d48:	2400      	movs	r4, #0
 8003d4a:	45a0      	cmp	r8, r4
 8003d4c:	d941      	bls.n	8003dd2 <sf_firmware_upgrade+0x12a>
        // show some progress
        if((pos % 4096) == 0) {
 8003d4e:	f3c4 030b 	ubfx	r3, r4, #0, #12
 8003d52:	b933      	cbnz	r3, 8003d62 <sf_firmware_upgrade+0xba>
            oled_show_progress(screen_upgrading, pos*100/size);
 8003d54:	2164      	movs	r1, #100	; 0x64
 8003d56:	4361      	muls	r1, r4
 8003d58:	482c      	ldr	r0, [pc, #176]	; (8003e0c <sf_firmware_upgrade+0x164>)
 8003d5a:	fbb1 f1f8 	udiv	r1, r1, r8
 8003d5e:	f7fc ffab 	bl	8000cb8 <oled_show_progress>
        }

        if(sf_read(pos, sizeof(tmp), tmp) != HAL_OK) {
 8003d62:	aa40      	add	r2, sp, #256	; 0x100
 8003d64:	f44f 7180 	mov.w	r1, #256	; 0x100
 8003d68:	4620      	mov	r0, r4
 8003d6a:	f7ff fe89 	bl	8003a80 <sf_read>
 8003d6e:	b110      	cbz	r0, 8003d76 <sf_firmware_upgrade+0xce>
            INCONSISTENT();
 8003d70:	4827      	ldr	r0, [pc, #156]	; (8003e10 <sf_firmware_upgrade+0x168>)
 8003d72:	f7fc fb2b 	bl	80003cc <fatal_error>
 8003d76:	f104 6300 	add.w	r3, r4, #134217728	; 0x8000000
 8003d7a:	f503 4500 	add.w	r5, r3, #32768	; 0x8000
 8003d7e:	f10d 09f8 	add.w	r9, sp, #248	; 0xf8
 8003d82:	f503 4601 	add.w	r6, r3, #33024	; 0x8100
        }

        uint32_t addr = FIRMWARE_START + pos;
        uint64_t *b = (uint64_t *)tmp;

        for(int i=0; i<sizeof(tmp)/sizeof(uint64_t); i++) {
 8003d86:	42b5      	cmp	r5, r6
 8003d88:	d014      	beq.n	8003db4 <sf_firmware_upgrade+0x10c>
            int rv;

            if(addr % FLASH_PAGE_SIZE == 0) {
 8003d8a:	f3c5 030a 	ubfx	r3, r5, #0, #11
 8003d8e:	b933      	cbnz	r3, 8003d9e <sf_firmware_upgrade+0xf6>
                rv = flash_page_erase(addr);
 8003d90:	4628      	mov	r0, r5
 8003d92:	f002 fddd 	bl	8006950 <__flash_page_erase_veneer>
                ASSERT(rv == 0);
 8003d96:	b110      	cbz	r0, 8003d9e <sf_firmware_upgrade+0xf6>
 8003d98:	481b      	ldr	r0, [pc, #108]	; (8003e08 <sf_firmware_upgrade+0x160>)
 8003d9a:	f7fc fb17 	bl	80003cc <fatal_error>
            }

            rv = flash_burn(addr, *(b++));
 8003d9e:	e9f9 2302 	ldrd	r2, r3, [r9, #8]!
 8003da2:	4628      	mov	r0, r5
 8003da4:	f002 fdcc 	bl	8006940 <__flash_burn_veneer>
            ASSERT(rv == 0);
 8003da8:	b110      	cbz	r0, 8003db0 <sf_firmware_upgrade+0x108>
 8003daa:	4817      	ldr	r0, [pc, #92]	; (8003e08 <sf_firmware_upgrade+0x160>)
 8003dac:	f7fc fb0e 	bl	80003cc <fatal_error>
            addr += sizeof(uint64_t);
 8003db0:	3508      	adds	r5, #8
 8003db2:	e7e8      	b.n	8003d86 <sf_firmware_upgrade+0xde>
        }

        if(dfu_button_pressed() && !flash_is_security_level2()) {
 8003db4:	f7ff f99a 	bl	80030ec <dfu_button_pressed>
 8003db8:	b140      	cbz	r0, 8003dcc <sf_firmware_upgrade+0x124>
 8003dba:	4b16      	ldr	r3, [pc, #88]	; (8003e14 <sf_firmware_upgrade+0x16c>)
 8003dbc:	6a1b      	ldr	r3, [r3, #32]
 8003dbe:	b2db      	uxtb	r3, r3
 8003dc0:	2bcc      	cmp	r3, #204	; 0xcc
 8003dc2:	d003      	beq.n	8003dcc <sf_firmware_upgrade+0x124>
            flash_lock();
 8003dc4:	f7fd ff0e 	bl	8001be4 <flash_lock>

            dfu_by_request();
 8003dc8:	f7fc fb9e 	bl	8000508 <dfu_by_request>

    flash_unlock();

    uint8_t     tmp[256] __attribute__((aligned(8)));

    for(uint32_t pos=0; pos<size; pos += sizeof(tmp)) {
 8003dcc:	f504 7480 	add.w	r4, r4, #256	; 0x100
 8003dd0:	e7bb      	b.n	8003d4a <sf_firmware_upgrade+0xa2>

            dfu_by_request();
        }
    }

    flash_lock();
 8003dd2:	f7fd ff07 	bl	8001be4 <flash_lock>
    }

    // Start the upgrade ... takes about a minute.
    sf_do_upgrade(hdr.firmware_length);

    if(hdr.install_flags & FWHIF_HIGH_WATER) {
 8003dd6:	9b07      	ldr	r3, [sp, #28]
 8003dd8:	07db      	lsls	r3, r3, #31
 8003dda:	d502      	bpl.n	8003de2 <sf_firmware_upgrade+0x13a>
        // set a new high-waterlevel for future versions.
        // ignore failures, since we can't recover anyway
        record_highwater_version(hdr.timestamp);
 8003ddc:	a801      	add	r0, sp, #4
 8003dde:	f7fe f889 	bl	8001ef4 <record_highwater_version>
    }

    // We're done, so clear header 
    uint8_t zeros[128] = { 0 };
 8003de2:	2280      	movs	r2, #128	; 0x80
 8003de4:	2100      	movs	r1, #0
 8003de6:	a840      	add	r0, sp, #256	; 0x100
 8003de8:	f002 fd84 	bl	80068f4 <memset>
    sf_write(off, sizeof(zeros), zeros);
 8003dec:	a940      	add	r1, sp, #256	; 0x100
 8003dee:	4638      	mov	r0, r7
 8003df0:	f7ff fe7a 	bl	8003ae8 <sf_write.constprop.1>

    // tell python, ultimately, that it worked.
    sf_completed_upgrade = SF_COMPLETED_UPGRADE;
 8003df4:	4b08      	ldr	r3, [pc, #32]	; (8003e18 <sf_firmware_upgrade+0x170>)
 8003df6:	4a09      	ldr	r2, [pc, #36]	; (8003e1c <sf_firmware_upgrade+0x174>)
 8003df8:	601a      	str	r2, [r3, #0]
}
 8003dfa:	f50d 7d01 	add.w	sp, sp, #516	; 0x204
 8003dfe:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}
 8003e02:	bf00      	nop
 8003e04:	08006f19 	.word	0x08006f19
 8003e08:	08006960 	.word	0x08006960
 8003e0c:	08006ba4 	.word	0x08006ba4
 8003e10:	08007230 	.word	0x08007230
 8003e14:	40022000 	.word	0x40022000
 8003e18:	1000634c 	.word	0x1000634c
 8003e1c:	b50d5c24 	.word	0xb50d5c24

08003e20 <HAL_InitTick>:

/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal.h"

// unwanted junk
HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority) { return 0; }
 8003e20:	2000      	movs	r0, #0
 8003e22:	4770      	bx	lr

08003e24 <HAL_RCC_DeInit>:
  * @retval None
  */
void HAL_RCC_DeInit(void)
{
  /* Set MSION bit */
  SET_BIT(RCC->CR, RCC_CR_MSION);
 8003e24:	4b17      	ldr	r3, [pc, #92]	; (8003e84 <HAL_RCC_DeInit+0x60>)
 8003e26:	681a      	ldr	r2, [r3, #0]
 8003e28:	f042 0201 	orr.w	r2, r2, #1
 8003e2c:	601a      	str	r2, [r3, #0]
 8003e2e:	461a      	mov	r2, r3

  /* Insure MSIRDY bit is set before writing default MSIRANGE value */
  while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); }
 8003e30:	6811      	ldr	r1, [r2, #0]
 8003e32:	4b14      	ldr	r3, [pc, #80]	; (8003e84 <HAL_RCC_DeInit+0x60>)
 8003e34:	0789      	lsls	r1, r1, #30
 8003e36:	d401      	bmi.n	8003e3c <HAL_RCC_DeInit+0x18>
  \brief   No Operation
  \details No Operation does nothing. This instruction can be used for code alignment purposes.
 */
__attribute__((always_inline)) __STATIC_INLINE void __NOP(void)
{
  __ASM volatile ("nop");
 8003e38:	bf00      	nop
 8003e3a:	e7f9      	b.n	8003e30 <HAL_RCC_DeInit+0xc>

  /* Set MSIRANGE default value */
  MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6);
 8003e3c:	681a      	ldr	r2, [r3, #0]
  CLEAR_REG(RCC->CFGR);

  /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */
#if defined(RCC_PLLSAI2_SUPPORT)

  CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON);
 8003e3e:	4912      	ldr	r1, [pc, #72]	; (8003e88 <HAL_RCC_DeInit+0x64>)

  /* Insure MSIRDY bit is set before writing default MSIRANGE value */
  while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET) { __NOP(); }

  /* Set MSIRANGE default value */
  MODIFY_REG(RCC->CR, RCC_CR_MSIRANGE, RCC_MSIRANGE_6);
 8003e40:	f022 02f0 	bic.w	r2, r2, #240	; 0xf0
 8003e44:	f042 0260 	orr.w	r2, r2, #96	; 0x60
 8003e48:	601a      	str	r2, [r3, #0]

  /* Reset CFGR register (MSI is selected as system clock source) */
  CLEAR_REG(RCC->CFGR);
 8003e4a:	2200      	movs	r2, #0
 8003e4c:	609a      	str	r2, [r3, #8]

  /* Reset HSION, HSIKERON, HSIASFS, HSEON, HSECSSON, PLLON, PLLSAIxON bits */
#if defined(RCC_PLLSAI2_SUPPORT)

  CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON | RCC_CR_PLLSAI2ON);
 8003e4e:	6818      	ldr	r0, [r3, #0]
 8003e50:	4001      	ands	r1, r0
 8003e52:	6019      	str	r1, [r3, #0]
  CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSION | RCC_CR_HSIKERON| RCC_CR_HSIASFS | RCC_CR_PLLON | RCC_CR_PLLSAI1ON);

#endif /* RCC_PLLSAI2_SUPPORT */

  /* Reset PLLCFGR register */
  CLEAR_REG(RCC->PLLCFGR);
 8003e54:	60da      	str	r2, [r3, #12]
  SET_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN_4 );
 8003e56:	68d9      	ldr	r1, [r3, #12]
 8003e58:	f441 5180 	orr.w	r1, r1, #4096	; 0x1000
 8003e5c:	60d9      	str	r1, [r3, #12]

  /* Reset PLLSAI1CFGR register */
  CLEAR_REG(RCC->PLLSAI1CFGR);
 8003e5e:	611a      	str	r2, [r3, #16]
  SET_BIT(RCC->PLLSAI1CFGR,  RCC_PLLSAI1CFGR_PLLSAI1N_4 );
 8003e60:	6919      	ldr	r1, [r3, #16]
 8003e62:	f441 5180 	orr.w	r1, r1, #4096	; 0x1000
 8003e66:	6119      	str	r1, [r3, #16]

#if defined(RCC_PLLSAI2_SUPPORT)

  /* Reset PLLSAI2CFGR register */
  CLEAR_REG(RCC->PLLSAI2CFGR);
 8003e68:	615a      	str	r2, [r3, #20]
  SET_BIT(RCC->PLLSAI2CFGR,  RCC_PLLSAI2CFGR_PLLSAI2N_4 );
 8003e6a:	6959      	ldr	r1, [r3, #20]
 8003e6c:	f441 5180 	orr.w	r1, r1, #4096	; 0x1000
 8003e70:	6159      	str	r1, [r3, #20]

#endif /* RCC_PLLSAI2_SUPPORT */

  /* Reset HSEBYP bit */
  CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
 8003e72:	6819      	ldr	r1, [r3, #0]
 8003e74:	f421 2180 	bic.w	r1, r1, #262144	; 0x40000
 8003e78:	6019      	str	r1, [r3, #0]

  /* Disable all interrupts */
  CLEAR_REG(RCC->CIER);
 8003e7a:	619a      	str	r2, [r3, #24]

  /* Update the SystemCoreClock global variable */
  SystemCoreClock = MSI_VALUE;
 8003e7c:	4b03      	ldr	r3, [pc, #12]	; (8003e8c <HAL_RCC_DeInit+0x68>)
 8003e7e:	4a04      	ldr	r2, [pc, #16]	; (8003e90 <HAL_RCC_DeInit+0x6c>)
 8003e80:	601a      	str	r2, [r3, #0]
 8003e82:	4770      	bx	lr
 8003e84:	40021000 	.word	0x40021000
 8003e88:	eafef4ff 	.word	0xeafef4ff
 8003e8c:	10006348 	.word	0x10006348
 8003e90:	003d0900 	.word	0x003d0900

08003e94 <HAL_RCC_MCOConfig>:
  *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
  *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
  * @retval None
  */
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
 8003e94:	b570      	push	{r4, r5, r6, lr}
  assert_param(IS_RCC_MCO(RCC_MCOx));
  assert_param(IS_RCC_MCODIV(RCC_MCODiv));
  assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));

  /* MCO Clock Enable */
  __MCO1_CLK_ENABLE();
 8003e96:	4c11      	ldr	r4, [pc, #68]	; (8003edc <HAL_RCC_MCOConfig+0x48>)
 8003e98:	6ce3      	ldr	r3, [r4, #76]	; 0x4c
 8003e9a:	f043 0301 	orr.w	r3, r3, #1
 8003e9e:	64e3      	str	r3, [r4, #76]	; 0x4c
 8003ea0:	6ce3      	ldr	r3, [r4, #76]	; 0x4c
  *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
  *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
  * @retval None
  */
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
 8003ea2:	b086      	sub	sp, #24
  assert_param(IS_RCC_MCO(RCC_MCOx));
  assert_param(IS_RCC_MCODIV(RCC_MCODiv));
  assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));

  /* MCO Clock Enable */
  __MCO1_CLK_ENABLE();
 8003ea4:	f003 0301 	and.w	r3, r3, #1
 8003ea8:	9300      	str	r3, [sp, #0]
 8003eaa:	9b00      	ldr	r3, [sp, #0]

  /* Configue the MCO1 pin in alternate function mode */
  GPIO_InitStruct.Pin = MCO1_PIN;
 8003eac:	f44f 7380 	mov.w	r3, #256	; 0x100
 8003eb0:	9301      	str	r3, [sp, #4]
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 8003eb2:	2302      	movs	r3, #2
 8003eb4:	9302      	str	r3, [sp, #8]
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 8003eb6:	9304      	str	r3, [sp, #16]
  *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
  *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
  * @retval None
  */
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
 8003eb8:	460d      	mov	r5, r1

  /* Configue the MCO1 pin in alternate function mode */
  GPIO_InitStruct.Pin = MCO1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 8003eba:	2300      	movs	r3, #0
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
  HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
 8003ebc:	a901      	add	r1, sp, #4
 8003ebe:	f04f 4090 	mov.w	r0, #1207959552	; 0x48000000
  *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
  *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
  * @retval None
  */
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
 8003ec2:	4616      	mov	r6, r2

  /* Configue the MCO1 pin in alternate function mode */
  GPIO_InitStruct.Pin = MCO1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
 8003ec4:	9303      	str	r3, [sp, #12]
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
 8003ec6:	9305      	str	r3, [sp, #20]
  HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);
 8003ec8:	f7fc ff76 	bl	8000db8 <HAL_GPIO_Init>

  /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */
  MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv ));
 8003ecc:	68a2      	ldr	r2, [r4, #8]
 8003ece:	f022 42ee 	bic.w	r2, r2, #1996488704	; 0x77000000
 8003ed2:	4316      	orrs	r6, r2
 8003ed4:	4335      	orrs	r5, r6
 8003ed6:	60a5      	str	r5, [r4, #8]
}
 8003ed8:	b006      	add	sp, #24
 8003eda:	bd70      	pop	{r4, r5, r6, pc}
 8003edc:	40021000 	.word	0x40021000

08003ee0 <HAL_RCC_GetSysClockFreq>:
uint32_t HAL_RCC_GetSysClockFreq(void)
{
  uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
  uint32_t sysclockfreq = 0U;

  if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ||
 8003ee0:	4932      	ldr	r1, [pc, #200]	; (8003fac <HAL_RCC_GetSysClockFreq+0xcc>)
 8003ee2:	688b      	ldr	r3, [r1, #8]
 8003ee4:	f013 0f0c 	tst.w	r3, #12
  *
  *
  * @retval SYSCLK frequency
  */
uint32_t HAL_RCC_GetSysClockFreq(void)
{
 8003ee8:	b510      	push	{r4, lr}
  uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
  uint32_t sysclockfreq = 0U;

  if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ||
 8003eea:	d009      	beq.n	8003f00 <HAL_RCC_GetSysClockFreq+0x20>
     ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI)))
 8003eec:	688b      	ldr	r3, [r1, #8]
uint32_t HAL_RCC_GetSysClockFreq(void)
{
  uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
  uint32_t sysclockfreq = 0U;

  if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) ||
 8003eee:	f003 030c 	and.w	r3, r3, #12
 8003ef2:	2b0c      	cmp	r3, #12
 8003ef4:	d11a      	bne.n	8003f2c <HAL_RCC_GetSysClockFreq+0x4c>
     ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI)))
 8003ef6:	68cb      	ldr	r3, [r1, #12]
 8003ef8:	f003 0303 	and.w	r3, r3, #3
 8003efc:	2b01      	cmp	r3, #1
 8003efe:	d115      	bne.n	8003f2c <HAL_RCC_GetSysClockFreq+0x4c>
  {
    /* MSI or PLL with MSI source used as system clock source */

    /* Get SYSCLK source */
    if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET)
 8003f00:	680a      	ldr	r2, [r1, #0]
 8003f02:	4b2a      	ldr	r3, [pc, #168]	; (8003fac <HAL_RCC_GetSysClockFreq+0xcc>)
 8003f04:	0712      	lsls	r2, r2, #28
    { /* MSISRANGE from RCC_CSR applies */
      msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
 8003f06:	bf54      	ite	pl
 8003f08:	f8d3 3094 	ldrpl.w	r3, [r3, #148]	; 0x94
    }
    else
    { /* MSIRANGE from RCC_CR applies */
      msirange = (RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
 8003f0c:	681b      	ldrmi	r3, [r3, #0]
    }
    /*MSI frequency range in HZ*/
    msirange = MSIRangeTable[msirange];
 8003f0e:	4a28      	ldr	r2, [pc, #160]	; (8003fb0 <HAL_RCC_GetSysClockFreq+0xd0>)
    /* MSI or PLL with MSI source used as system clock source */

    /* Get SYSCLK source */
    if(READ_BIT(RCC->CR, RCC_CR_MSIRGSEL) == RESET)
    { /* MSISRANGE from RCC_CSR applies */
      msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> RCC_CSR_MSISRANGE_Pos;
 8003f10:	bf54      	ite	pl
 8003f12:	f3c3 2303 	ubfxpl	r3, r3, #8, #4
    }
    else
    { /* MSIRANGE from RCC_CR applies */
      msirange = (RCC->CR & RCC_CR_MSIRANGE) >> RCC_CR_MSIRANGE_Pos;
 8003f16:	f3c3 1303 	ubfxmi	r3, r3, #4, #4
    }
    /*MSI frequency range in HZ*/
    msirange = MSIRangeTable[msirange];
 8003f1a:	f852 4023 	ldr.w	r4, [r2, r3, lsl #2]

    if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI)
 8003f1e:	688b      	ldr	r3, [r1, #8]
    {
      /* MSI used as system clock source */
      sysclockfreq = msirange;
 8003f20:	f013 0f0c 	tst.w	r3, #12
 8003f24:	bf0c      	ite	eq
 8003f26:	4620      	moveq	r0, r4
 8003f28:	2000      	movne	r0, #0
 8003f2a:	e011      	b.n	8003f50 <HAL_RCC_GetSysClockFreq+0x70>
    }
  }
  else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
 8003f2c:	688b      	ldr	r3, [r1, #8]
 8003f2e:	f003 030c 	and.w	r3, r3, #12
 8003f32:	2b04      	cmp	r3, #4
 8003f34:	d007      	beq.n	8003f46 <HAL_RCC_GetSysClockFreq+0x66>
  {
    /* HSI used as system clock source */
    sysclockfreq = HSI_VALUE;
  }
  else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE)
 8003f36:	4b1d      	ldr	r3, [pc, #116]	; (8003fac <HAL_RCC_GetSysClockFreq+0xcc>)
 8003f38:	689b      	ldr	r3, [r3, #8]
 8003f3a:	f003 030c 	and.w	r3, r3, #12
 8003f3e:	2b08      	cmp	r3, #8
 8003f40:	d104      	bne.n	8003f4c <HAL_RCC_GetSysClockFreq+0x6c>
  {
    /* HSE used as system clock source */
    sysclockfreq = HSE_VALUE;
 8003f42:	481c      	ldr	r0, [pc, #112]	; (8003fb4 <HAL_RCC_GetSysClockFreq+0xd4>)
 8003f44:	e000      	b.n	8003f48 <HAL_RCC_GetSysClockFreq+0x68>
    }
  }
  else if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI)
  {
    /* HSI used as system clock source */
    sysclockfreq = HSI_VALUE;
 8003f46:	481c      	ldr	r0, [pc, #112]	; (8003fb8 <HAL_RCC_GetSysClockFreq+0xd8>)
  *
  * @retval SYSCLK frequency
  */
uint32_t HAL_RCC_GetSysClockFreq(void)
{
  uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
 8003f48:	2400      	movs	r4, #0
 8003f4a:	e001      	b.n	8003f50 <HAL_RCC_GetSysClockFreq+0x70>
  uint32_t sysclockfreq = 0U;
 8003f4c:	2000      	movs	r0, #0
  *
  * @retval SYSCLK frequency
  */
uint32_t HAL_RCC_GetSysClockFreq(void)
{
  uint32_t msirange = 0U, pllvco = 0U, pllsource = 0U, pllr = 2U, pllm = 2U;
 8003f4e:	4604      	mov	r4, r0
  {
    /* HSE used as system clock source */
    sysclockfreq = HSE_VALUE;
  }

  if(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL)
 8003f50:	688a      	ldr	r2, [r1, #8]
 8003f52:	4b16      	ldr	r3, [pc, #88]	; (8003fac <HAL_RCC_GetSysClockFreq+0xcc>)
 8003f54:	f002 020c 	and.w	r2, r2, #12
 8003f58:	2a0c      	cmp	r2, #12
 8003f5a:	d126      	bne.n	8003faa <HAL_RCC_GetSysClockFreq+0xca>
    /* PLL used as system clock  source */

    /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
    SYSCLK = PLL_VCO / PLLR
    */
    pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
 8003f5c:	68da      	ldr	r2, [r3, #12]
    pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
 8003f5e:	68d8      	ldr	r0, [r3, #12]

    switch (pllsource)
 8003f60:	f002 0203 	and.w	r2, r2, #3

    /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
    SYSCLK = PLL_VCO / PLLR
    */
    pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
    pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
 8003f64:	f3c0 1002 	ubfx	r0, r0, #4, #3

    switch (pllsource)
 8003f68:	2a02      	cmp	r2, #2

    /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
    SYSCLK = PLL_VCO / PLLR
    */
    pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
    pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;
 8003f6a:	f100 0001 	add.w	r0, r0, #1

    switch (pllsource)
 8003f6e:	d006      	beq.n	8003f7e <HAL_RCC_GetSysClockFreq+0x9e>
 8003f70:	2a03      	cmp	r2, #3
 8003f72:	d10c      	bne.n	8003f8e <HAL_RCC_GetSysClockFreq+0xae>
    case RCC_PLLSOURCE_HSI:  /* HSI used as PLL clock source */
      pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
      break;

    case RCC_PLLSOURCE_HSE:  /* HSE used as PLL clock source */
      pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
 8003f74:	68db      	ldr	r3, [r3, #12]
 8003f76:	4a0f      	ldr	r2, [pc, #60]	; (8003fb4 <HAL_RCC_GetSysClockFreq+0xd4>)
 8003f78:	f3c3 2306 	ubfx	r3, r3, #8, #7
 8003f7c:	e003      	b.n	8003f86 <HAL_RCC_GetSysClockFreq+0xa6>
    pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U ;

    switch (pllsource)
    {
    case RCC_PLLSOURCE_HSI:  /* HSI used as PLL clock source */
      pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
 8003f7e:	68db      	ldr	r3, [r3, #12]
 8003f80:	4a0d      	ldr	r2, [pc, #52]	; (8003fb8 <HAL_RCC_GetSysClockFreq+0xd8>)
 8003f82:	f3c3 2306 	ubfx	r3, r3, #8, #7
      break;

    case RCC_PLLSOURCE_HSE:  /* HSE used as PLL clock source */
      pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
 8003f86:	fbb2 f0f0 	udiv	r0, r2, r0
 8003f8a:	4343      	muls	r3, r0
      break;
 8003f8c:	e006      	b.n	8003f9c <HAL_RCC_GetSysClockFreq+0xbc>

    case RCC_PLLSOURCE_MSI:  /* MSI used as PLL clock source */
    default:
      pllvco = (msirange / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
 8003f8e:	68da      	ldr	r2, [r3, #12]
 8003f90:	fbb4 f0f0 	udiv	r0, r4, r0
 8003f94:	f3c2 2206 	ubfx	r2, r2, #8, #7
 8003f98:	fb00 f302 	mul.w	r3, r0, r2
      break;
    }
    pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U ) * 2U;
 8003f9c:	68c8      	ldr	r0, [r1, #12]
    sysclockfreq = pllvco/pllr;
 8003f9e:	f3c0 6041 	ubfx	r0, r0, #25, #2
 8003fa2:	3001      	adds	r0, #1
 8003fa4:	0040      	lsls	r0, r0, #1
 8003fa6:	fbb3 f0f0 	udiv	r0, r3, r0
  }

  return sysclockfreq;
}
 8003faa:	bd10      	pop	{r4, pc}
 8003fac:	40021000 	.word	0x40021000
 8003fb0:	08006988 	.word	0x08006988
 8003fb4:	007a1200 	.word	0x007a1200
 8003fb8:	00f42400 	.word	0x00f42400

08003fbc <HAL_RCC_OscConfig>:
  /* Check the parameters */
  assert_param(RCC_OscInitStruct != NULL);
  assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));

  /*----------------------------- MSI Configuration --------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
 8003fbc:	6803      	ldr	r3, [r0, #0]
  *         supported by this macro. User should request a transition to HSE Off
  *         first and then HSE On or HSE Bypass.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
 8003fbe:	e92d 41f3 	stmdb	sp!, {r0, r1, r4, r5, r6, r7, r8, lr}
  /* Check the parameters */
  assert_param(RCC_OscInitStruct != NULL);
  assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));

  /*----------------------------- MSI Configuration --------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
 8003fc2:	06dd      	lsls	r5, r3, #27
  *         supported by this macro. User should request a transition to HSE Off
  *         first and then HSE On or HSE Bypass.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
 8003fc4:	4604      	mov	r4, r0
  /* Check the parameters */
  assert_param(RCC_OscInitStruct != NULL);
  assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));

  /*----------------------------- MSI Configuration --------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_MSI) == RCC_OSCILLATORTYPE_MSI)
 8003fc6:	d564      	bpl.n	8004092 <HAL_RCC_OscConfig+0xd6>
    assert_param(IS_RCC_MSI(RCC_OscInitStruct->MSIState));
    assert_param(IS_RCC_MSICALIBRATION_VALUE(RCC_OscInitStruct->MSICalibrationValue));
    assert_param(IS_RCC_MSI_CLOCK_RANGE(RCC_OscInitStruct->MSIClockRange));

    /* When the MSI is used as system clock it will not be disabled */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_MSI) )
 8003fc8:	4da2      	ldr	r5, [pc, #648]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 8003fca:	68ab      	ldr	r3, [r5, #8]
 8003fcc:	f013 0f0c 	tst.w	r3, #12
 8003fd0:	d129      	bne.n	8004026 <HAL_RCC_OscConfig+0x6a>
    {
      if((READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET) && (RCC_OscInitStruct->MSIState == RCC_MSI_OFF))
 8003fd2:	682b      	ldr	r3, [r5, #0]
 8003fd4:	0798      	lsls	r0, r3, #30
 8003fd6:	d503      	bpl.n	8003fe0 <HAL_RCC_OscConfig+0x24>
 8003fd8:	69a3      	ldr	r3, [r4, #24]
 8003fda:	b90b      	cbnz	r3, 8003fe0 <HAL_RCC_OscConfig+0x24>
      {
        return HAL_ERROR;
 8003fdc:	2001      	movs	r0, #1
 8003fde:	e1f7      	b.n	80043d0 <HAL_RCC_OscConfig+0x414>
      else
      {
        /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
           must be correctly programmed according to the frequency of the CPU clock
           (HCLK) and the supply voltage of the device. */
        if(RCC_OscInitStruct->MSIClockRange > __HAL_RCC_GET_MSI_RANGE())
 8003fe0:	6829      	ldr	r1, [r5, #0]
 8003fe2:	4b9c      	ldr	r3, [pc, #624]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 8003fe4:	6a22      	ldr	r2, [r4, #32]
 8003fe6:	0709      	lsls	r1, r1, #28
 8003fe8:	bf4c      	ite	mi
 8003fea:	681b      	ldrmi	r3, [r3, #0]
 8003fec:	f8d3 3094 	ldrpl.w	r3, [r3, #148]	; 0x94
          {
            return HAL_ERROR;
          }

          /* Selects the Multiple Speed oscillator (MSI) clock range .*/
          __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
 8003ff0:	682b      	ldr	r3, [r5, #0]
 8003ff2:	f043 0308 	orr.w	r3, r3, #8
 8003ff6:	602b      	str	r3, [r5, #0]
 8003ff8:	682b      	ldr	r3, [r5, #0]
 8003ffa:	f023 03f0 	bic.w	r3, r3, #240	; 0xf0
 8003ffe:	431a      	orrs	r2, r3
 8004000:	602a      	str	r2, [r5, #0]
          /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
          __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
 8004002:	686b      	ldr	r3, [r5, #4]
 8004004:	69e2      	ldr	r2, [r4, #28]
 8004006:	f423 437f 	bic.w	r3, r3, #65280	; 0xff00
 800400a:	ea43 2302 	orr.w	r3, r3, r2, lsl #8
 800400e:	606b      	str	r3, [r5, #4]
            return HAL_ERROR;
          }
        }

        /* Update the SystemCoreClock global variable */
        SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
 8004010:	f7ff ff66 	bl	8003ee0 <HAL_RCC_GetSysClockFreq>
 8004014:	68ab      	ldr	r3, [r5, #8]
 8004016:	4a90      	ldr	r2, [pc, #576]	; (8004258 <HAL_RCC_OscConfig+0x29c>)
 8004018:	f3c3 1303 	ubfx	r3, r3, #4, #4
 800401c:	5cd3      	ldrb	r3, [r2, r3]
 800401e:	40d8      	lsrs	r0, r3
 8004020:	4b8e      	ldr	r3, [pc, #568]	; (800425c <HAL_RCC_OscConfig+0x2a0>)
 8004022:	6018      	str	r0, [r3, #0]
 8004024:	e035      	b.n	8004092 <HAL_RCC_OscConfig+0xd6>
      }
    }
    else
    {
      /* Check the MSI State */
      if(RCC_OscInitStruct->MSIState != RCC_MSI_OFF)
 8004026:	6983      	ldr	r3, [r0, #24]
 8004028:	b31b      	cbz	r3, 8004072 <HAL_RCC_OscConfig+0xb6>
      {
        /* Enable the Internal High Speed oscillator (MSI). */
        __HAL_RCC_MSI_ENABLE();
 800402a:	682b      	ldr	r3, [r5, #0]
 800402c:	f043 0301 	orr.w	r3, r3, #1
 8004030:	602b      	str	r3, [r5, #0]

        /* Get timeout */
        tickstart = HAL_GetTick();
 8004032:	f7fc fd01 	bl	8000a38 <HAL_GetTick>
 8004036:	4606      	mov	r6, r0

        /* Wait till MSI is ready */
        while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET)
 8004038:	682a      	ldr	r2, [r5, #0]
 800403a:	4b86      	ldr	r3, [pc, #536]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 800403c:	0792      	lsls	r2, r2, #30
 800403e:	d406      	bmi.n	800404e <HAL_RCC_OscConfig+0x92>
        {
          if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
 8004040:	f7fc fcfa 	bl	8000a38 <HAL_GetTick>
 8004044:	1b80      	subs	r0, r0, r6
 8004046:	2802      	cmp	r0, #2
 8004048:	d9f6      	bls.n	8004038 <HAL_RCC_OscConfig+0x7c>
          {
            return HAL_TIMEOUT;
 800404a:	2003      	movs	r0, #3
 800404c:	e1c0      	b.n	80043d0 <HAL_RCC_OscConfig+0x414>
          }
        }
         /* Selects the Multiple Speed oscillator (MSI) clock range .*/
        __HAL_RCC_MSI_RANGE_CONFIG(RCC_OscInitStruct->MSIClockRange);
 800404e:	681a      	ldr	r2, [r3, #0]
 8004050:	f042 0208 	orr.w	r2, r2, #8
 8004054:	601a      	str	r2, [r3, #0]
 8004056:	681a      	ldr	r2, [r3, #0]
 8004058:	f022 01f0 	bic.w	r1, r2, #240	; 0xf0
 800405c:	6a22      	ldr	r2, [r4, #32]
 800405e:	430a      	orrs	r2, r1
 8004060:	601a      	str	r2, [r3, #0]
         /* Adjusts the Multiple Speed oscillator (MSI) calibration value.*/
        __HAL_RCC_MSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->MSICalibrationValue);
 8004062:	685a      	ldr	r2, [r3, #4]
 8004064:	69e1      	ldr	r1, [r4, #28]
 8004066:	f422 427f 	bic.w	r2, r2, #65280	; 0xff00
 800406a:	ea42 2201 	orr.w	r2, r2, r1, lsl #8
 800406e:	605a      	str	r2, [r3, #4]
 8004070:	e00f      	b.n	8004092 <HAL_RCC_OscConfig+0xd6>

      }
      else
      {
        /* Disable the Internal High Speed oscillator (MSI). */
        __HAL_RCC_MSI_DISABLE();
 8004072:	682b      	ldr	r3, [r5, #0]
 8004074:	f023 0301 	bic.w	r3, r3, #1
 8004078:	602b      	str	r3, [r5, #0]

        /* Get timeout */
        tickstart = HAL_GetTick();
 800407a:	f7fc fcdd 	bl	8000a38 <HAL_GetTick>
 800407e:	4606      	mov	r6, r0

        /* Wait till MSI is ready */
        while(READ_BIT(RCC->CR, RCC_CR_MSIRDY) != RESET)
 8004080:	682b      	ldr	r3, [r5, #0]
 8004082:	079f      	lsls	r7, r3, #30
 8004084:	d505      	bpl.n	8004092 <HAL_RCC_OscConfig+0xd6>
        {
          if((HAL_GetTick() - tickstart) > MSI_TIMEOUT_VALUE)
 8004086:	f7fc fcd7 	bl	8000a38 <HAL_GetTick>
 800408a:	1b80      	subs	r0, r0, r6
 800408c:	2802      	cmp	r0, #2
 800408e:	d9f7      	bls.n	8004080 <HAL_RCC_OscConfig+0xc4>
 8004090:	e7db      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
        }
      }
    }
  }
  /*------------------------------- HSE Configuration ------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
 8004092:	6823      	ldr	r3, [r4, #0]
 8004094:	07de      	lsls	r6, r3, #31
 8004096:	d403      	bmi.n	80040a0 <HAL_RCC_OscConfig+0xe4>
        }
      }
    }
  }
  /*----------------------------- HSI Configuration --------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
 8004098:	6823      	ldr	r3, [r4, #0]
 800409a:	079d      	lsls	r5, r3, #30
 800409c:	d448      	bmi.n	8004130 <HAL_RCC_OscConfig+0x174>
 800409e:	e091      	b.n	80041c4 <HAL_RCC_OscConfig+0x208>
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));

    /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||
 80040a0:	4d6c      	ldr	r5, [pc, #432]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 80040a2:	68ab      	ldr	r3, [r5, #8]
 80040a4:	f003 030c 	and.w	r3, r3, #12
 80040a8:	2b08      	cmp	r3, #8
 80040aa:	d009      	beq.n	80040c0 <HAL_RCC_OscConfig+0x104>
       ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
 80040ac:	68ab      	ldr	r3, [r5, #8]
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));

    /* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||
 80040ae:	f003 030c 	and.w	r3, r3, #12
 80040b2:	2b0c      	cmp	r3, #12
 80040b4:	d10b      	bne.n	80040ce <HAL_RCC_OscConfig+0x112>
       ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
 80040b6:	68eb      	ldr	r3, [r5, #12]
 80040b8:	f003 0303 	and.w	r3, r3, #3
 80040bc:	2b03      	cmp	r3, #3
 80040be:	d106      	bne.n	80040ce <HAL_RCC_OscConfig+0x112>
    {
      if((READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
 80040c0:	682b      	ldr	r3, [r5, #0]
 80040c2:	0398      	lsls	r0, r3, #14
 80040c4:	d5e8      	bpl.n	8004098 <HAL_RCC_OscConfig+0xdc>
 80040c6:	6863      	ldr	r3, [r4, #4]
 80040c8:	2b00      	cmp	r3, #0
 80040ca:	d1e5      	bne.n	8004098 <HAL_RCC_OscConfig+0xdc>
 80040cc:	e786      	b.n	8003fdc <HAL_RCC_OscConfig+0x20>
      }
    }
    else
    {
      /* Set the new HSE configuration ---------------------------------------*/
      __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
 80040ce:	6863      	ldr	r3, [r4, #4]
 80040d0:	f5b3 3f80 	cmp.w	r3, #65536	; 0x10000
 80040d4:	d006      	beq.n	80040e4 <HAL_RCC_OscConfig+0x128>
 80040d6:	f5b3 2fa0 	cmp.w	r3, #327680	; 0x50000
 80040da:	d108      	bne.n	80040ee <HAL_RCC_OscConfig+0x132>
 80040dc:	682b      	ldr	r3, [r5, #0]
 80040de:	f443 2380 	orr.w	r3, r3, #262144	; 0x40000
 80040e2:	602b      	str	r3, [r5, #0]
 80040e4:	682b      	ldr	r3, [r5, #0]
 80040e6:	f443 3380 	orr.w	r3, r3, #65536	; 0x10000
 80040ea:	602b      	str	r3, [r5, #0]
 80040ec:	e008      	b.n	8004100 <HAL_RCC_OscConfig+0x144>
 80040ee:	682a      	ldr	r2, [r5, #0]
 80040f0:	f422 3280 	bic.w	r2, r2, #65536	; 0x10000
 80040f4:	602a      	str	r2, [r5, #0]
 80040f6:	682a      	ldr	r2, [r5, #0]
 80040f8:	f422 2280 	bic.w	r2, r2, #262144	; 0x40000
 80040fc:	602a      	str	r2, [r5, #0]

      /* Check the HSE State */
      if(RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
 80040fe:	b15b      	cbz	r3, 8004118 <HAL_RCC_OscConfig+0x15c>
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 8004100:	f7fc fc9a 	bl	8000a38 <HAL_GetTick>
 8004104:	4606      	mov	r6, r0

        /* Wait till HSE is ready */
        while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
 8004106:	682b      	ldr	r3, [r5, #0]
 8004108:	0399      	lsls	r1, r3, #14
 800410a:	d4c5      	bmi.n	8004098 <HAL_RCC_OscConfig+0xdc>
        {
          if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
 800410c:	f7fc fc94 	bl	8000a38 <HAL_GetTick>
 8004110:	1b80      	subs	r0, r0, r6
 8004112:	2864      	cmp	r0, #100	; 0x64
 8004114:	d9f7      	bls.n	8004106 <HAL_RCC_OscConfig+0x14a>
 8004116:	e798      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
        }
      }
      else
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 8004118:	f7fc fc8e 	bl	8000a38 <HAL_GetTick>
 800411c:	4606      	mov	r6, r0

        /* Wait till HSE is disabled */
        while(READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
 800411e:	682b      	ldr	r3, [r5, #0]
 8004120:	039a      	lsls	r2, r3, #14
 8004122:	d5b9      	bpl.n	8004098 <HAL_RCC_OscConfig+0xdc>
        {
          if((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
 8004124:	f7fc fc88 	bl	8000a38 <HAL_GetTick>
 8004128:	1b80      	subs	r0, r0, r6
 800412a:	2864      	cmp	r0, #100	; 0x64
 800412c:	d9f7      	bls.n	800411e <HAL_RCC_OscConfig+0x162>
 800412e:	e78c      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
    /* Check the parameters */
    assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
    assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));

    /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||
 8004130:	4d48      	ldr	r5, [pc, #288]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 8004132:	68ab      	ldr	r3, [r5, #8]
 8004134:	f003 030c 	and.w	r3, r3, #12
 8004138:	2b04      	cmp	r3, #4
 800413a:	d009      	beq.n	8004150 <HAL_RCC_OscConfig+0x194>
       ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI)))
 800413c:	68ab      	ldr	r3, [r5, #8]
    /* Check the parameters */
    assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
    assert_param(IS_RCC_HSI_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));

    /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||
 800413e:	f003 030c 	and.w	r3, r3, #12
 8004142:	2b0c      	cmp	r3, #12
 8004144:	d113      	bne.n	800416e <HAL_RCC_OscConfig+0x1b2>
       ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI)))
 8004146:	68eb      	ldr	r3, [r5, #12]
 8004148:	f003 0303 	and.w	r3, r3, #3
 800414c:	2b02      	cmp	r3, #2
 800414e:	d10e      	bne.n	800416e <HAL_RCC_OscConfig+0x1b2>
    {
      /* When HSI is used as system clock it will not be disabled */
      if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
 8004150:	682b      	ldr	r3, [r5, #0]
 8004152:	055b      	lsls	r3, r3, #21
 8004154:	d503      	bpl.n	800415e <HAL_RCC_OscConfig+0x1a2>
 8004156:	68e3      	ldr	r3, [r4, #12]
 8004158:	2b00      	cmp	r3, #0
 800415a:	f43f af3f 	beq.w	8003fdc <HAL_RCC_OscConfig+0x20>
      }
      /* Otherwise, just the calibration is allowed */
      else
      {
        /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
 800415e:	686b      	ldr	r3, [r5, #4]
 8004160:	6922      	ldr	r2, [r4, #16]
 8004162:	f023 53f8 	bic.w	r3, r3, #520093696	; 0x1f000000
 8004166:	ea43 6302 	orr.w	r3, r3, r2, lsl #24
 800416a:	606b      	str	r3, [r5, #4]
    /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||
       ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI)))
    {
      /* When HSI is used as system clock it will not be disabled */
      if((READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState == RCC_HSI_OFF))
 800416c:	e02a      	b.n	80041c4 <HAL_RCC_OscConfig+0x208>
      }
    }
    else
    {
      /* Check the HSI State */
      if(RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
 800416e:	68e3      	ldr	r3, [r4, #12]
 8004170:	b1c3      	cbz	r3, 80041a4 <HAL_RCC_OscConfig+0x1e8>
      {
        /* Enable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_ENABLE();
 8004172:	682b      	ldr	r3, [r5, #0]
 8004174:	f443 7380 	orr.w	r3, r3, #256	; 0x100
 8004178:	602b      	str	r3, [r5, #0]

        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 800417a:	f7fc fc5d 	bl	8000a38 <HAL_GetTick>
 800417e:	4606      	mov	r6, r0

        /* Wait till HSI is ready */
        while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
 8004180:	682b      	ldr	r3, [r5, #0]
 8004182:	4a34      	ldr	r2, [pc, #208]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 8004184:	055f      	lsls	r7, r3, #21
 8004186:	d405      	bmi.n	8004194 <HAL_RCC_OscConfig+0x1d8>
        {
          if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
 8004188:	f7fc fc56 	bl	8000a38 <HAL_GetTick>
 800418c:	1b80      	subs	r0, r0, r6
 800418e:	2802      	cmp	r0, #2
 8004190:	d9f6      	bls.n	8004180 <HAL_RCC_OscConfig+0x1c4>
 8004192:	e75a      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
            return HAL_TIMEOUT;
          }
        }

        /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
 8004194:	6853      	ldr	r3, [r2, #4]
 8004196:	6921      	ldr	r1, [r4, #16]
 8004198:	f023 53f8 	bic.w	r3, r3, #520093696	; 0x1f000000
 800419c:	ea43 6301 	orr.w	r3, r3, r1, lsl #24
 80041a0:	6053      	str	r3, [r2, #4]
 80041a2:	e00f      	b.n	80041c4 <HAL_RCC_OscConfig+0x208>
      }
      else
      {
        /* Disable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_DISABLE();
 80041a4:	682b      	ldr	r3, [r5, #0]
 80041a6:	f423 7380 	bic.w	r3, r3, #256	; 0x100
 80041aa:	602b      	str	r3, [r5, #0]

        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 80041ac:	f7fc fc44 	bl	8000a38 <HAL_GetTick>
 80041b0:	4606      	mov	r6, r0

        /* Wait till HSI is disabled */
        while(READ_BIT(RCC->CR, RCC_CR_HSIRDY) != RESET)
 80041b2:	682b      	ldr	r3, [r5, #0]
 80041b4:	0558      	lsls	r0, r3, #21
 80041b6:	d505      	bpl.n	80041c4 <HAL_RCC_OscConfig+0x208>
        {
          if((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
 80041b8:	f7fc fc3e 	bl	8000a38 <HAL_GetTick>
 80041bc:	1b80      	subs	r0, r0, r6
 80041be:	2802      	cmp	r0, #2
 80041c0:	d9f7      	bls.n	80041b2 <HAL_RCC_OscConfig+0x1f6>
 80041c2:	e742      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
        }
      }
    }
  }
  /*------------------------------ LSI Configuration -------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
 80041c4:	6823      	ldr	r3, [r4, #0]
 80041c6:	0719      	lsls	r1, r3, #28
 80041c8:	d403      	bmi.n	80041d2 <HAL_RCC_OscConfig+0x216>
        }
      }
    }
  }
  /*------------------------------ LSE Configuration -------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
 80041ca:	6823      	ldr	r3, [r4, #0]
 80041cc:	075a      	lsls	r2, r3, #29
 80041ce:	d429      	bmi.n	8004224 <HAL_RCC_OscConfig+0x268>
 80041d0:	e099      	b.n	8004306 <HAL_RCC_OscConfig+0x34a>
  {
    /* Check the parameters */
    assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));

    /* Check the LSI State */
    if(RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
 80041d2:	6963      	ldr	r3, [r4, #20]
 80041d4:	4d1f      	ldr	r5, [pc, #124]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 80041d6:	b193      	cbz	r3, 80041fe <HAL_RCC_OscConfig+0x242>
    {
      /* Enable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_ENABLE();
 80041d8:	f8d5 3094 	ldr.w	r3, [r5, #148]	; 0x94
 80041dc:	f043 0301 	orr.w	r3, r3, #1
 80041e0:	f8c5 3094 	str.w	r3, [r5, #148]	; 0x94

      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80041e4:	f7fc fc28 	bl	8000a38 <HAL_GetTick>
 80041e8:	4606      	mov	r6, r0

      /* Wait till LSI is ready */
      while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) == RESET)
 80041ea:	f8d5 3094 	ldr.w	r3, [r5, #148]	; 0x94
 80041ee:	079b      	lsls	r3, r3, #30
 80041f0:	d4eb      	bmi.n	80041ca <HAL_RCC_OscConfig+0x20e>
      {
        if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
 80041f2:	f7fc fc21 	bl	8000a38 <HAL_GetTick>
 80041f6:	1b80      	subs	r0, r0, r6
 80041f8:	2802      	cmp	r0, #2
 80041fa:	d9f6      	bls.n	80041ea <HAL_RCC_OscConfig+0x22e>
 80041fc:	e725      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
      }
    }
    else
    {
      /* Disable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_DISABLE();
 80041fe:	f8d5 3094 	ldr.w	r3, [r5, #148]	; 0x94
 8004202:	f023 0301 	bic.w	r3, r3, #1
 8004206:	f8c5 3094 	str.w	r3, [r5, #148]	; 0x94

      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 800420a:	f7fc fc15 	bl	8000a38 <HAL_GetTick>
 800420e:	4606      	mov	r6, r0

      /* Wait till LSI is disabled */
      while(READ_BIT(RCC->CSR, RCC_CSR_LSIRDY) != RESET)
 8004210:	f8d5 3094 	ldr.w	r3, [r5, #148]	; 0x94
 8004214:	079f      	lsls	r7, r3, #30
 8004216:	d5d8      	bpl.n	80041ca <HAL_RCC_OscConfig+0x20e>
      {
        if((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
 8004218:	f7fc fc0e 	bl	8000a38 <HAL_GetTick>
 800421c:	1b80      	subs	r0, r0, r6
 800421e:	2802      	cmp	r0, #2
 8004220:	d9f6      	bls.n	8004210 <HAL_RCC_OscConfig+0x254>
 8004222:	e712      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
    /* Check the parameters */
    assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));

    /* Update LSE configuration in Backup Domain control register    */
    /* Requires to enable write access to Backup Domain of necessary */
    if(HAL_IS_BIT_CLR(RCC->APB1ENR1, RCC_APB1ENR1_PWREN))
 8004224:	4d0b      	ldr	r5, [pc, #44]	; (8004254 <HAL_RCC_OscConfig+0x298>)
 8004226:	6dab      	ldr	r3, [r5, #88]	; 0x58
 8004228:	00de      	lsls	r6, r3, #3
 800422a:	d40a      	bmi.n	8004242 <HAL_RCC_OscConfig+0x286>
    {
      __HAL_RCC_PWR_CLK_ENABLE();
 800422c:	6dab      	ldr	r3, [r5, #88]	; 0x58
 800422e:	f043 5380 	orr.w	r3, r3, #268435456	; 0x10000000
 8004232:	65ab      	str	r3, [r5, #88]	; 0x58
 8004234:	6dab      	ldr	r3, [r5, #88]	; 0x58
 8004236:	f003 5380 	and.w	r3, r3, #268435456	; 0x10000000
 800423a:	9301      	str	r3, [sp, #4]
 800423c:	9b01      	ldr	r3, [sp, #4]
      pwrclkchanged = SET;
 800423e:	2701      	movs	r7, #1
 8004240:	e000      	b.n	8004244 <HAL_RCC_OscConfig+0x288>
    }
  }
  /*------------------------------ LSE Configuration -------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
  {
    FlagStatus       pwrclkchanged = RESET;
 8004242:	2700      	movs	r7, #0
    {
      __HAL_RCC_PWR_CLK_ENABLE();
      pwrclkchanged = SET;
    }

    if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
 8004244:	4e06      	ldr	r6, [pc, #24]	; (8004260 <HAL_RCC_OscConfig+0x2a4>)
 8004246:	6833      	ldr	r3, [r6, #0]
 8004248:	05d8      	lsls	r0, r3, #23
 800424a:	d50b      	bpl.n	8004264 <HAL_RCC_OscConfig+0x2a8>
        }
      }
    }

    /* Set the new LSE configuration -----------------------------------------*/
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
 800424c:	68a3      	ldr	r3, [r4, #8]
 800424e:	2b01      	cmp	r3, #1
 8004250:	d119      	bne.n	8004286 <HAL_RCC_OscConfig+0x2ca>
 8004252:	e020      	b.n	8004296 <HAL_RCC_OscConfig+0x2da>
 8004254:	40021000 	.word	0x40021000
 8004258:	08006970 	.word	0x08006970
 800425c:	10006348 	.word	0x10006348
 8004260:	40007000 	.word	0x40007000
    }

    if(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
    {
      /* Enable write access to Backup domain */
      SET_BIT(PWR->CR1, PWR_CR1_DBP);
 8004264:	6833      	ldr	r3, [r6, #0]
 8004266:	f443 7380 	orr.w	r3, r3, #256	; 0x100
 800426a:	6033      	str	r3, [r6, #0]

      /* Wait for Backup domain Write protection disable */
      tickstart = HAL_GetTick();
 800426c:	f7fc fbe4 	bl	8000a38 <HAL_GetTick>
 8004270:	4680      	mov	r8, r0

      while(HAL_IS_BIT_CLR(PWR->CR1, PWR_CR1_DBP))
 8004272:	6833      	ldr	r3, [r6, #0]
 8004274:	05d9      	lsls	r1, r3, #23
 8004276:	d4e9      	bmi.n	800424c <HAL_RCC_OscConfig+0x290>
      {
        if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
 8004278:	f7fc fbde 	bl	8000a38 <HAL_GetTick>
 800427c:	ebc8 0000 	rsb	r0, r8, r0
 8004280:	2802      	cmp	r0, #2
 8004282:	d9f6      	bls.n	8004272 <HAL_RCC_OscConfig+0x2b6>
 8004284:	e6e1      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
        }
      }
    }

    /* Set the new LSE configuration -----------------------------------------*/
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
 8004286:	2b05      	cmp	r3, #5
 8004288:	d10c      	bne.n	80042a4 <HAL_RCC_OscConfig+0x2e8>
 800428a:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90
 800428e:	f043 0304 	orr.w	r3, r3, #4
 8004292:	f8c5 3090 	str.w	r3, [r5, #144]	; 0x90
 8004296:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90
 800429a:	f043 0301 	orr.w	r3, r3, #1
 800429e:	f8c5 3090 	str.w	r3, [r5, #144]	; 0x90
 80042a2:	e00c      	b.n	80042be <HAL_RCC_OscConfig+0x302>
 80042a4:	f8d5 2090 	ldr.w	r2, [r5, #144]	; 0x90
 80042a8:	f022 0201 	bic.w	r2, r2, #1
 80042ac:	f8c5 2090 	str.w	r2, [r5, #144]	; 0x90
 80042b0:	f8d5 2090 	ldr.w	r2, [r5, #144]	; 0x90
 80042b4:	f022 0204 	bic.w	r2, r2, #4
 80042b8:	f8c5 2090 	str.w	r2, [r5, #144]	; 0x90

    /* Check the LSE State */
    if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
 80042bc:	b173      	cbz	r3, 80042dc <HAL_RCC_OscConfig+0x320>
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80042be:	f7fc fbbb 	bl	8000a38 <HAL_GetTick>

      /* Wait till LSE is ready */
      while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 80042c2:	f241 3888 	movw	r8, #5000	; 0x1388

    /* Check the LSE State */
    if(RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80042c6:	4606      	mov	r6, r0

      /* Wait till LSE is ready */
      while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
 80042c8:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90
 80042cc:	079a      	lsls	r2, r3, #30
 80042ce:	d40e      	bmi.n	80042ee <HAL_RCC_OscConfig+0x332>
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 80042d0:	f7fc fbb2 	bl	8000a38 <HAL_GetTick>
 80042d4:	1b80      	subs	r0, r0, r6
 80042d6:	4540      	cmp	r0, r8
 80042d8:	d9f6      	bls.n	80042c8 <HAL_RCC_OscConfig+0x30c>
 80042da:	e6b6      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
      }
    }
    else
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80042dc:	f7fc fbac 	bl	8000a38 <HAL_GetTick>

      /* Wait till LSE is disabled */
      while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET)
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 80042e0:	f241 3888 	movw	r8, #5000	; 0x1388
      }
    }
    else
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80042e4:	4606      	mov	r6, r0

      /* Wait till LSE is disabled */
      while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET)
 80042e6:	f8d5 3090 	ldr.w	r3, [r5, #144]	; 0x90
 80042ea:	079b      	lsls	r3, r3, #30
 80042ec:	d405      	bmi.n	80042fa <HAL_RCC_OscConfig+0x33e>
        }
      }
    }

    /* Restore clock configuration if changed */
    if(pwrclkchanged == SET)
 80042ee:	b157      	cbz	r7, 8004306 <HAL_RCC_OscConfig+0x34a>
    {
      __HAL_RCC_PWR_CLK_DISABLE();
 80042f0:	6dab      	ldr	r3, [r5, #88]	; 0x58
 80042f2:	f023 5380 	bic.w	r3, r3, #268435456	; 0x10000000
 80042f6:	65ab      	str	r3, [r5, #88]	; 0x58
 80042f8:	e005      	b.n	8004306 <HAL_RCC_OscConfig+0x34a>
      tickstart = HAL_GetTick();

      /* Wait till LSE is disabled */
      while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) != RESET)
      {
        if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 80042fa:	f7fc fb9d 	bl	8000a38 <HAL_GetTick>
 80042fe:	1b80      	subs	r0, r0, r6
 8004300:	4540      	cmp	r0, r8
 8004302:	d9f0      	bls.n	80042e6 <HAL_RCC_OscConfig+0x32a>
 8004304:	e6a1      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
#endif /* RCC_HSI48_SUPPORT */
  /*-------------------------------- PLL Configuration -----------------------*/
  /* Check the parameters */
  assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));

  if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
 8004306:	6aa2      	ldr	r2, [r4, #40]	; 0x28
 8004308:	b90a      	cbnz	r2, 800430e <HAL_RCC_OscConfig+0x352>
    else
    {
      return HAL_ERROR;
    }
  }
  return HAL_OK;
 800430a:	2000      	movs	r0, #0
 800430c:	e060      	b.n	80043d0 <HAL_RCC_OscConfig+0x414>
  assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));

  if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
 800430e:	4d32      	ldr	r5, [pc, #200]	; (80043d8 <HAL_RCC_OscConfig+0x41c>)
 8004310:	68ab      	ldr	r3, [r5, #8]
 8004312:	f003 030c 	and.w	r3, r3, #12
 8004316:	2b0c      	cmp	r3, #12
 8004318:	f43f ae60 	beq.w	8003fdc <HAL_RCC_OscConfig+0x20>
        assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
        assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
        assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));

        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();
 800431c:	682b      	ldr	r3, [r5, #0]
  if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
    {
      if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
 800431e:	2a02      	cmp	r2, #2
        assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
        assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));
        assert_param(IS_RCC_PLLR_VALUE(RCC_OscInitStruct->PLL.PLLR));

        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();
 8004320:	f023 7380 	bic.w	r3, r3, #16777216	; 0x1000000
 8004324:	602b      	str	r3, [r5, #0]
  if(RCC_OscInitStruct->PLL.PLLState != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
    {
      if(RCC_OscInitStruct->PLL.PLLState == RCC_PLL_ON)
 8004326:	d137      	bne.n	8004398 <HAL_RCC_OscConfig+0x3dc>

        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();

        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 8004328:	f7fc fb86 	bl	8000a38 <HAL_GetTick>
 800432c:	4606      	mov	r6, r0

        /* Wait till PLL is ready */
        while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
 800432e:	682b      	ldr	r3, [r5, #0]
 8004330:	4829      	ldr	r0, [pc, #164]	; (80043d8 <HAL_RCC_OscConfig+0x41c>)
 8004332:	019f      	lsls	r7, r3, #6
 8004334:	d505      	bpl.n	8004342 <HAL_RCC_OscConfig+0x386>
        {
          if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
 8004336:	f7fc fb7f 	bl	8000a38 <HAL_GetTick>
 800433a:	1b80      	subs	r0, r0, r6
 800433c:	2802      	cmp	r0, #2
 800433e:	d9f6      	bls.n	800432e <HAL_RCC_OscConfig+0x372>
 8004340:	e683      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
            return HAL_TIMEOUT;
          }
        }

        /* Configure the main PLL clock source, multiplication and division factors. */
        __HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
 8004342:	6b61      	ldr	r1, [r4, #52]	; 0x34
 8004344:	6ae3      	ldr	r3, [r4, #44]	; 0x2c
 8004346:	6ba2      	ldr	r2, [r4, #56]	; 0x38
 8004348:	ea43 2301 	orr.w	r3, r3, r1, lsl #8
 800434c:	6b21      	ldr	r1, [r4, #48]	; 0x30
 800434e:	3901      	subs	r1, #1
 8004350:	ea43 1301 	orr.w	r3, r3, r1, lsl #4
 8004354:	0912      	lsrs	r2, r2, #4
 8004356:	ea43 4142 	orr.w	r1, r3, r2, lsl #17
 800435a:	6be3      	ldr	r3, [r4, #60]	; 0x3c
 800435c:	085b      	lsrs	r3, r3, #1
 800435e:	3b01      	subs	r3, #1
 8004360:	ea41 5243 	orr.w	r2, r1, r3, lsl #21
 8004364:	6c23      	ldr	r3, [r4, #64]	; 0x40
 8004366:	085b      	lsrs	r3, r3, #1
 8004368:	3b01      	subs	r3, #1
 800436a:	ea42 6343 	orr.w	r3, r2, r3, lsl #25
 800436e:	60c3      	str	r3, [r0, #12]
                             RCC_OscInitStruct->PLL.PLLP,
                             RCC_OscInitStruct->PLL.PLLQ,
                             RCC_OscInitStruct->PLL.PLLR);

        /* Enable the main PLL. */
        __HAL_RCC_PLL_ENABLE();
 8004370:	6803      	ldr	r3, [r0, #0]
 8004372:	f043 7380 	orr.w	r3, r3, #16777216	; 0x1000000
 8004376:	6003      	str	r3, [r0, #0]

        /* Enable PLL System Clock output. */
         __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SYSCLK);
 8004378:	68c3      	ldr	r3, [r0, #12]
 800437a:	f043 7380 	orr.w	r3, r3, #16777216	; 0x1000000
 800437e:	60c3      	str	r3, [r0, #12]

        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 8004380:	f7fc fb5a 	bl	8000a38 <HAL_GetTick>
 8004384:	4604      	mov	r4, r0

        /* Wait till PLL is ready */
        while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET)
 8004386:	682b      	ldr	r3, [r5, #0]
 8004388:	0198      	lsls	r0, r3, #6
 800438a:	d4be      	bmi.n	800430a <HAL_RCC_OscConfig+0x34e>
        {
          if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
 800438c:	f7fc fb54 	bl	8000a38 <HAL_GetTick>
 8004390:	1b00      	subs	r0, r0, r4
 8004392:	2802      	cmp	r0, #2
 8004394:	d9f7      	bls.n	8004386 <HAL_RCC_OscConfig+0x3ca>
 8004396:	e658      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
      {
        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();

        /* Disable all PLL outputs to save power if no PLLs on */
        if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
 8004398:	682b      	ldr	r3, [r5, #0]
 800439a:	0119      	lsls	r1, r3, #4
 800439c:	d406      	bmi.n	80043ac <HAL_RCC_OscConfig+0x3f0>
#if defined(RCC_PLLSAI2_SUPPORT)
           &&
           (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
 800439e:	682b      	ldr	r3, [r5, #0]
        __HAL_RCC_PLL_DISABLE();

        /* Disable all PLL outputs to save power if no PLLs on */
        if((READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
#if defined(RCC_PLLSAI2_SUPPORT)
           &&
 80043a0:	009a      	lsls	r2, r3, #2
           (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
#endif /* RCC_PLLSAI2_SUPPORT */
          )
        {
          MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
 80043a2:	bf5e      	ittt	pl
 80043a4:	68eb      	ldrpl	r3, [r5, #12]
 80043a6:	f023 0303 	bicpl.w	r3, r3, #3
 80043aa:	60eb      	strpl	r3, [r5, #12]
        }

#if defined(RCC_PLLSAI2_SUPPORT)
        __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI3CLK);
 80043ac:	68eb      	ldr	r3, [r5, #12]
 80043ae:	f023 7388 	bic.w	r3, r3, #17825792	; 0x1100000
 80043b2:	f423 3380 	bic.w	r3, r3, #65536	; 0x10000
 80043b6:	60eb      	str	r3, [r5, #12]
#else
        __HAL_RCC_PLLCLKOUT_DISABLE(RCC_PLL_SYSCLK | RCC_PLL_48M1CLK | RCC_PLL_SAI2CLK);
#endif /* RCC_PLLSAI2_SUPPORT */

        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 80043b8:	f7fc fb3e 	bl	8000a38 <HAL_GetTick>
 80043bc:	4604      	mov	r4, r0

        /* Wait till PLL is disabled */
        while(READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
 80043be:	682b      	ldr	r3, [r5, #0]
 80043c0:	019b      	lsls	r3, r3, #6
 80043c2:	d5a2      	bpl.n	800430a <HAL_RCC_OscConfig+0x34e>
        {
          if((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
 80043c4:	f7fc fb38 	bl	8000a38 <HAL_GetTick>
 80043c8:	1b00      	subs	r0, r0, r4
 80043ca:	2802      	cmp	r0, #2
 80043cc:	d9f7      	bls.n	80043be <HAL_RCC_OscConfig+0x402>
 80043ce:	e63c      	b.n	800404a <HAL_RCC_OscConfig+0x8e>
    {
      return HAL_ERROR;
    }
  }
  return HAL_OK;
}
 80043d0:	b002      	add	sp, #8
 80043d2:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 80043d6:	bf00      	nop
 80043d8:	40021000 	.word	0x40021000

080043dc <HAL_RCC_ClockConfig>:
  /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
    must be correctly programmed according to the frequency of the CPU clock
    (HCLK) and the supply voltage of the device. */

  /* Increasing the number of wait states because of higher CPU frequency */
  if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY))
 80043dc:	4a53      	ldr	r2, [pc, #332]	; (800452c <HAL_RCC_ClockConfig+0x150>)
 80043de:	6813      	ldr	r3, [r2, #0]
 80043e0:	f003 0307 	and.w	r3, r3, #7
 80043e4:	428b      	cmp	r3, r1
  *         HPRE[3:0] bits to ensure that HCLK not exceed the maximum allowed frequency
  *         (for more details refer to section above "Initialization/de-initialization functions")
  * @retval None
  */
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef  *RCC_ClkInitStruct, uint32_t FLatency)
{
 80043e6:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
 80043ea:	4605      	mov	r5, r0
 80043ec:	460e      	mov	r6, r1
  /* To correctly read data from FLASH memory, the number of wait states (LATENCY)
    must be correctly programmed according to the frequency of the CPU clock
    (HCLK) and the supply voltage of the device. */

  /* Increasing the number of wait states because of higher CPU frequency */
  if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY))
 80043ee:	d30a      	bcc.n	8004406 <HAL_RCC_ClockConfig+0x2a>
      return HAL_ERROR;
    }
  }

  /*-------------------------- HCLK Configuration --------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
 80043f0:	6829      	ldr	r1, [r5, #0]
 80043f2:	0788      	lsls	r0, r1, #30
 80043f4:	d514      	bpl.n	8004420 <HAL_RCC_ClockConfig+0x44>
  {
    assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
 80043f6:	484e      	ldr	r0, [pc, #312]	; (8004530 <HAL_RCC_ClockConfig+0x154>)
 80043f8:	6883      	ldr	r3, [r0, #8]
 80043fa:	f023 02f0 	bic.w	r2, r3, #240	; 0xf0
 80043fe:	68ab      	ldr	r3, [r5, #8]
 8004400:	4313      	orrs	r3, r2
 8004402:	6083      	str	r3, [r0, #8]
 8004404:	e00c      	b.n	8004420 <HAL_RCC_ClockConfig+0x44>

  /* Increasing the number of wait states because of higher CPU frequency */
  if(FLatency > (FLASH->ACR & FLASH_ACR_LATENCY))
  {
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    __HAL_FLASH_SET_LATENCY(FLatency);
 8004406:	6813      	ldr	r3, [r2, #0]
 8004408:	f023 0307 	bic.w	r3, r3, #7
 800440c:	430b      	orrs	r3, r1
 800440e:	6013      	str	r3, [r2, #0]

    /* Check that the new number of wait states is taken into account to access the Flash
    memory by reading the FLASH_ACR register */
    if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency)
 8004410:	6813      	ldr	r3, [r2, #0]
 8004412:	f003 0307 	and.w	r3, r3, #7
 8004416:	4299      	cmp	r1, r3
 8004418:	d0ea      	beq.n	80043f0 <HAL_RCC_ClockConfig+0x14>
    {
      return HAL_ERROR;
 800441a:	2001      	movs	r0, #1
 800441c:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
    assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
  }

  /*------------------------- SYSCLK Configuration ---------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
 8004420:	07ca      	lsls	r2, r1, #31
 8004422:	d406      	bmi.n	8004432 <HAL_RCC_ClockConfig+0x56>
      }
    }
  }

  /* Decreasing the number of wait states because of lower CPU frequency */
  if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY))
 8004424:	4a41      	ldr	r2, [pc, #260]	; (800452c <HAL_RCC_ClockConfig+0x150>)
 8004426:	6813      	ldr	r3, [r2, #0]
 8004428:	f003 0307 	and.w	r3, r3, #7
 800442c:	429e      	cmp	r6, r3
 800442e:	d351      	bcc.n	80044d4 <HAL_RCC_ClockConfig+0xf8>
 8004430:	e05a      	b.n	80044e8 <HAL_RCC_ClockConfig+0x10c>
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
  {
    assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));

    /* HSE is selected as System Clock Source */
    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
 8004432:	686b      	ldr	r3, [r5, #4]
 8004434:	4c3e      	ldr	r4, [pc, #248]	; (8004530 <HAL_RCC_ClockConfig+0x154>)
 8004436:	2b02      	cmp	r3, #2
    {
      /* Check the HSE ready flag */
      if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
 8004438:	6822      	ldr	r2, [r4, #0]
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
  {
    assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));

    /* HSE is selected as System Clock Source */
    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
 800443a:	d102      	bne.n	8004442 <HAL_RCC_ClockConfig+0x66>
    {
      /* Check the HSE ready flag */
      if(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
 800443c:	f412 3f00 	tst.w	r2, #131072	; 0x20000
 8004440:	e00a      	b.n	8004458 <HAL_RCC_ClockConfig+0x7c>
      {
        return HAL_ERROR;
      }
    }
    /* PLL is selected as System Clock Source */
    else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
 8004442:	2b03      	cmp	r3, #3
 8004444:	d102      	bne.n	800444c <HAL_RCC_ClockConfig+0x70>
    {
      /* Check the PLL ready flag */
      if(READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET)
 8004446:	f012 7f00 	tst.w	r2, #33554432	; 0x2000000
 800444a:	e005      	b.n	8004458 <HAL_RCC_ClockConfig+0x7c>
      {
        return HAL_ERROR;
      }
    }
    /* MSI is selected as System Clock Source */
    else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
 800444c:	b913      	cbnz	r3, 8004454 <HAL_RCC_ClockConfig+0x78>
    {
      /* Check the MSI ready flag */
      if(READ_BIT(RCC->CR, RCC_CR_MSIRDY) == RESET)
 800444e:	f012 0f02 	tst.w	r2, #2
 8004452:	e001      	b.n	8004458 <HAL_RCC_ClockConfig+0x7c>
    }
    /* HSI is selected as System Clock Source */
    else
    {
      /* Check the HSI ready flag */
      if(READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
 8004454:	f412 6f80 	tst.w	r2, #1024	; 0x400
 8004458:	d0df      	beq.n	800441a <HAL_RCC_ClockConfig+0x3e>
      {
        return HAL_ERROR;
      }
    }
    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);
 800445a:	68a2      	ldr	r2, [r4, #8]
 800445c:	f022 0203 	bic.w	r2, r2, #3
 8004460:	4313      	orrs	r3, r2
 8004462:	60a3      	str	r3, [r4, #8]

    /* Get Start Tick*/
    tickstart = HAL_GetTick();
 8004464:	f7fc fae8 	bl	8000a38 <HAL_GetTick>

    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
 8004468:	686b      	ldr	r3, [r5, #4]
 800446a:	2b02      	cmp	r3, #2
      }
    }
    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);

    /* Get Start Tick*/
    tickstart = HAL_GetTick();
 800446c:	4607      	mov	r7, r0

    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
    {
      while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE)
      {
        if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
 800446e:	f241 3888 	movw	r8, #5000	; 0x1388
    MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);

    /* Get Start Tick*/
    tickstart = HAL_GetTick();

    if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
 8004472:	d10c      	bne.n	800448e <HAL_RCC_ClockConfig+0xb2>
    {
      while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSE)
 8004474:	68a3      	ldr	r3, [r4, #8]
 8004476:	f003 030c 	and.w	r3, r3, #12
 800447a:	2b08      	cmp	r3, #8
 800447c:	d0d2      	beq.n	8004424 <HAL_RCC_ClockConfig+0x48>
      {
        if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
 800447e:	f7fc fadb 	bl	8000a38 <HAL_GetTick>
 8004482:	1bc0      	subs	r0, r0, r7
 8004484:	4540      	cmp	r0, r8
 8004486:	d9f5      	bls.n	8004474 <HAL_RCC_ClockConfig+0x98>
        {
          return HAL_TIMEOUT;
 8004488:	2003      	movs	r0, #3
 800448a:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
        }
      }
    }
    else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
 800448e:	2b03      	cmp	r3, #3
 8004490:	d10a      	bne.n	80044a8 <HAL_RCC_ClockConfig+0xcc>
    {
      while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
 8004492:	68a3      	ldr	r3, [r4, #8]
 8004494:	f003 030c 	and.w	r3, r3, #12
 8004498:	2b0c      	cmp	r3, #12
 800449a:	d0c3      	beq.n	8004424 <HAL_RCC_ClockConfig+0x48>
      {
        if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
 800449c:	f7fc facc 	bl	8000a38 <HAL_GetTick>
 80044a0:	1bc0      	subs	r0, r0, r7
 80044a2:	4540      	cmp	r0, r8
 80044a4:	d9f5      	bls.n	8004492 <HAL_RCC_ClockConfig+0xb6>
 80044a6:	e7ef      	b.n	8004488 <HAL_RCC_ClockConfig+0xac>
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else if(RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_MSI)
 80044a8:	b973      	cbnz	r3, 80044c8 <HAL_RCC_ClockConfig+0xec>
    {
      while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_MSI)
 80044aa:	68a3      	ldr	r3, [r4, #8]
 80044ac:	f013 0f0c 	tst.w	r3, #12
 80044b0:	d0b8      	beq.n	8004424 <HAL_RCC_ClockConfig+0x48>
      {
        if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
 80044b2:	f7fc fac1 	bl	8000a38 <HAL_GetTick>
 80044b6:	1bc0      	subs	r0, r0, r7
 80044b8:	4540      	cmp	r0, r8
 80044ba:	d9f6      	bls.n	80044aa <HAL_RCC_ClockConfig+0xce>
 80044bc:	e7e4      	b.n	8004488 <HAL_RCC_ClockConfig+0xac>
    }
    else
    {
      while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI)
      {
        if((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
 80044be:	f7fc fabb 	bl	8000a38 <HAL_GetTick>
 80044c2:	1bc0      	subs	r0, r0, r7
 80044c4:	4540      	cmp	r0, r8
 80044c6:	d8df      	bhi.n	8004488 <HAL_RCC_ClockConfig+0xac>
        }
      }
    }
    else
    {
      while(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI)
 80044c8:	68a3      	ldr	r3, [r4, #8]
 80044ca:	f003 030c 	and.w	r3, r3, #12
 80044ce:	2b04      	cmp	r3, #4
 80044d0:	d1f5      	bne.n	80044be <HAL_RCC_ClockConfig+0xe2>
 80044d2:	e7a7      	b.n	8004424 <HAL_RCC_ClockConfig+0x48>

  /* Decreasing the number of wait states because of lower CPU frequency */
  if(FLatency < (FLASH->ACR & FLASH_ACR_LATENCY))
  {
    /* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
    __HAL_FLASH_SET_LATENCY(FLatency);
 80044d4:	6813      	ldr	r3, [r2, #0]
 80044d6:	f023 0307 	bic.w	r3, r3, #7
 80044da:	4333      	orrs	r3, r6
 80044dc:	6013      	str	r3, [r2, #0]

    /* Check that the new number of wait states is taken into account to access the Flash
    memory by reading the FLASH_ACR register */
    if((FLASH->ACR & FLASH_ACR_LATENCY) != FLatency)
 80044de:	6813      	ldr	r3, [r2, #0]
 80044e0:	f003 0307 	and.w	r3, r3, #7
 80044e4:	429e      	cmp	r6, r3
 80044e6:	d198      	bne.n	800441a <HAL_RCC_ClockConfig+0x3e>
      return HAL_ERROR;
    }
  }

  /*-------------------------- PCLK1 Configuration ---------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
 80044e8:	6829      	ldr	r1, [r5, #0]
 80044ea:	4c11      	ldr	r4, [pc, #68]	; (8004530 <HAL_RCC_ClockConfig+0x154>)
 80044ec:	f011 0f04 	tst.w	r1, #4
 80044f0:	d005      	beq.n	80044fe <HAL_RCC_ClockConfig+0x122>
  {
    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
 80044f2:	68a3      	ldr	r3, [r4, #8]
 80044f4:	f423 62e0 	bic.w	r2, r3, #1792	; 0x700
 80044f8:	68eb      	ldr	r3, [r5, #12]
 80044fa:	4313      	orrs	r3, r2
 80044fc:	60a3      	str	r3, [r4, #8]
  }

  /*-------------------------- PCLK2 Configuration ---------------------------*/
  if(((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
 80044fe:	070b      	lsls	r3, r1, #28
 8004500:	d506      	bpl.n	8004510 <HAL_RCC_ClockConfig+0x134>
  {
    assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
    MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3U));
 8004502:	68a3      	ldr	r3, [r4, #8]
 8004504:	692a      	ldr	r2, [r5, #16]
 8004506:	f423 5360 	bic.w	r3, r3, #14336	; 0x3800
 800450a:	ea43 03c2 	orr.w	r3, r3, r2, lsl #3
 800450e:	60a3      	str	r3, [r4, #8]
  }

  /* Update the SystemCoreClock global variable */
  SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
 8004510:	f7ff fce6 	bl	8003ee0 <HAL_RCC_GetSysClockFreq>
 8004514:	68a3      	ldr	r3, [r4, #8]
 8004516:	4a07      	ldr	r2, [pc, #28]	; (8004534 <HAL_RCC_ClockConfig+0x158>)
 8004518:	f3c3 1303 	ubfx	r3, r3, #4, #4
 800451c:	5cd3      	ldrb	r3, [r2, r3]
 800451e:	40d8      	lsrs	r0, r3
 8004520:	4b05      	ldr	r3, [pc, #20]	; (8004538 <HAL_RCC_ClockConfig+0x15c>)
 8004522:	6018      	str	r0, [r3, #0]

  /* Configure the source of time base considering new system clocks settings*/
  HAL_InitTick (TICK_INT_PRIORITY);

  return HAL_OK;
 8004524:	2000      	movs	r0, #0
}
 8004526:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}
 800452a:	bf00      	nop
 800452c:	40022000 	.word	0x40022000
 8004530:	40021000 	.word	0x40021000
 8004534:	08006970 	.word	0x08006970
 8004538:	10006348 	.word	0x10006348

0800453c <HAL_RCC_GetHCLKFreq>:
  * @retval HCLK frequency in Hz
  */
uint32_t HAL_RCC_GetHCLKFreq(void)
{
  return SystemCoreClock;
}
 800453c:	4b01      	ldr	r3, [pc, #4]	; (8004544 <HAL_RCC_GetHCLKFreq+0x8>)
 800453e:	6818      	ldr	r0, [r3, #0]
 8004540:	4770      	bx	lr
 8004542:	bf00      	nop
 8004544:	10006348 	.word	0x10006348

08004548 <HAL_RCC_GetPCLK1Freq>:
  * @retval PCLK1 frequency in Hz
  */
uint32_t HAL_RCC_GetPCLK1Freq(void)
{
  /* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
  return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]);
 8004548:	4b04      	ldr	r3, [pc, #16]	; (800455c <HAL_RCC_GetPCLK1Freq+0x14>)
 800454a:	4a05      	ldr	r2, [pc, #20]	; (8004560 <HAL_RCC_GetPCLK1Freq+0x18>)
 800454c:	689b      	ldr	r3, [r3, #8]
 800454e:	f3c3 2302 	ubfx	r3, r3, #8, #3
 8004552:	5cd3      	ldrb	r3, [r2, r3]
 8004554:	4a03      	ldr	r2, [pc, #12]	; (8004564 <HAL_RCC_GetPCLK1Freq+0x1c>)
 8004556:	6810      	ldr	r0, [r2, #0]
}
 8004558:	40d8      	lsrs	r0, r3
 800455a:	4770      	bx	lr
 800455c:	40021000 	.word	0x40021000
 8004560:	08006980 	.word	0x08006980
 8004564:	10006348 	.word	0x10006348

08004568 <HAL_RCC_GetPCLK2Freq>:
  * @retval PCLK2 frequency in Hz
  */
uint32_t HAL_RCC_GetPCLK2Freq(void)
{
  /* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
  return (HAL_RCC_GetHCLKFreq()>> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]);
 8004568:	4b04      	ldr	r3, [pc, #16]	; (800457c <HAL_RCC_GetPCLK2Freq+0x14>)
 800456a:	4a05      	ldr	r2, [pc, #20]	; (8004580 <HAL_RCC_GetPCLK2Freq+0x18>)
 800456c:	689b      	ldr	r3, [r3, #8]
 800456e:	f3c3 23c2 	ubfx	r3, r3, #11, #3
 8004572:	5cd3      	ldrb	r3, [r2, r3]
 8004574:	4a03      	ldr	r2, [pc, #12]	; (8004584 <HAL_RCC_GetPCLK2Freq+0x1c>)
 8004576:	6810      	ldr	r0, [r2, #0]
}
 8004578:	40d8      	lsrs	r0, r3
 800457a:	4770      	bx	lr
 800457c:	40021000 	.word	0x40021000
 8004580:	08006980 	.word	0x08006980
 8004584:	10006348 	.word	0x10006348

08004588 <HAL_RCC_GetOscConfig>:
  /* Set all possible values for the Oscillator type parameter ---------------*/
#if defined(RCC_HSI48_SUPPORT)
  RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
                                      RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_HSI48;
#else
  RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_MSI | \
 8004588:	231f      	movs	r3, #31
 800458a:	6003      	str	r3, [r0, #0]
                                      RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
#endif /* RCC_HSI48_SUPPORT */

  /* Get the HSE configuration -----------------------------------------------*/
  if((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
 800458c:	4b31      	ldr	r3, [pc, #196]	; (8004654 <HAL_RCC_GetOscConfig+0xcc>)
 800458e:	681a      	ldr	r2, [r3, #0]
 8004590:	0352      	lsls	r2, r2, #13
 8004592:	d502      	bpl.n	800459a <HAL_RCC_GetOscConfig+0x12>
  {
    RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
 8004594:	f44f 22a0 	mov.w	r2, #327680	; 0x50000
 8004598:	e005      	b.n	80045a6 <HAL_RCC_GetOscConfig+0x1e>
  }
  else if((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
 800459a:	681a      	ldr	r2, [r3, #0]
 800459c:	f412 3280 	ands.w	r2, r2, #65536	; 0x10000
  {
    RCC_OscInitStruct->HSEState = RCC_HSE_ON;
 80045a0:	bf18      	it	ne
 80045a2:	f44f 3280 	movne.w	r2, #65536	; 0x10000
  }
  else
  {
    RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
 80045a6:	6042      	str	r2, [r0, #4]
  }

   /* Get the MSI configuration -----------------------------------------------*/
  if((RCC->CR & RCC_CR_MSION) == RCC_CR_MSION)
 80045a8:	681a      	ldr	r2, [r3, #0]
 80045aa:	f012 0201 	ands.w	r2, r2, #1
  {
    RCC_OscInitStruct->MSIState = RCC_MSI_ON;
 80045ae:	bf18      	it	ne
 80045b0:	2201      	movne	r2, #1
  }
  else
  {
    RCC_OscInitStruct->MSIState = RCC_MSI_OFF;
 80045b2:	6182      	str	r2, [r0, #24]
  }

  RCC_OscInitStruct->MSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_MSITRIM) >> RCC_ICSCR_MSITRIM_Pos);
 80045b4:	685a      	ldr	r2, [r3, #4]
 80045b6:	f3c2 2207 	ubfx	r2, r2, #8, #8
 80045ba:	61c2      	str	r2, [r0, #28]
  RCC_OscInitStruct->MSIClockRange = (uint32_t)((RCC->CR & RCC_CR_MSIRANGE) );
 80045bc:	681a      	ldr	r2, [r3, #0]
 80045be:	f002 02f0 	and.w	r2, r2, #240	; 0xf0
 80045c2:	6202      	str	r2, [r0, #32]

  /* Get the HSI configuration -----------------------------------------------*/
  if((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
 80045c4:	681a      	ldr	r2, [r3, #0]
 80045c6:	f412 7280 	ands.w	r2, r2, #256	; 0x100
  {
    RCC_OscInitStruct->HSIState = RCC_HSI_ON;
 80045ca:	bf18      	it	ne
 80045cc:	f44f 7280 	movne.w	r2, #256	; 0x100
  }
  else
  {
    RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
 80045d0:	60c2      	str	r2, [r0, #12]
  }

  RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->ICSCR & RCC_ICSCR_HSITRIM) >> RCC_ICSCR_HSITRIM_Pos);
 80045d2:	685a      	ldr	r2, [r3, #4]
 80045d4:	f3c2 6204 	ubfx	r2, r2, #24, #5
 80045d8:	6102      	str	r2, [r0, #16]

  /* Get the LSE configuration -----------------------------------------------*/
  if((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
 80045da:	f8d3 2090 	ldr.w	r2, [r3, #144]	; 0x90
 80045de:	0751      	lsls	r1, r2, #29
 80045e0:	d501      	bpl.n	80045e6 <HAL_RCC_GetOscConfig+0x5e>
  {
    RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
 80045e2:	2205      	movs	r2, #5
 80045e4:	e006      	b.n	80045f4 <HAL_RCC_GetOscConfig+0x6c>
  }
  else if((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
 80045e6:	4a1b      	ldr	r2, [pc, #108]	; (8004654 <HAL_RCC_GetOscConfig+0xcc>)
 80045e8:	f8d2 2090 	ldr.w	r2, [r2, #144]	; 0x90
 80045ec:	f012 0201 	ands.w	r2, r2, #1
  {
    RCC_OscInitStruct->LSEState = RCC_LSE_ON;
 80045f0:	bf18      	it	ne
 80045f2:	2201      	movne	r2, #1
  }
  else
  {
    RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
 80045f4:	6082      	str	r2, [r0, #8]
  }

  /* Get the LSI configuration -----------------------------------------------*/
  if((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION)
 80045f6:	f8d3 2094 	ldr.w	r2, [r3, #148]	; 0x94
 80045fa:	f012 0201 	ands.w	r2, r2, #1
  {
    RCC_OscInitStruct->LSIState = RCC_LSI_ON;
 80045fe:	bf18      	it	ne
 8004600:	2201      	movne	r2, #1
  }
  else
  {
    RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
 8004602:	6142      	str	r2, [r0, #20]
  else
  {
    RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF;
  }
#else
  RCC_OscInitStruct->HSI48State = RCC_HSI48_OFF;
 8004604:	2200      	movs	r2, #0
 8004606:	6242      	str	r2, [r0, #36]	; 0x24
#endif /* RCC_HSI48_SUPPORT */

  /* Get the PLL configuration -----------------------------------------------*/
  if((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON)
 8004608:	681a      	ldr	r2, [r3, #0]
 800460a:	01d2      	lsls	r2, r2, #7
  {
    RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
 800460c:	bf4c      	ite	mi
 800460e:	2202      	movmi	r2, #2
  }
  else
  {
    RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
 8004610:	2201      	movpl	r2, #1
 8004612:	6282      	str	r2, [r0, #40]	; 0x28
  }
  RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
 8004614:	68da      	ldr	r2, [r3, #12]
 8004616:	f002 0203 	and.w	r2, r2, #3
 800461a:	62c2      	str	r2, [r0, #44]	; 0x2c
  RCC_OscInitStruct->PLL.PLLM = (uint32_t)(((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U);
 800461c:	68da      	ldr	r2, [r3, #12]
 800461e:	f3c2 1202 	ubfx	r2, r2, #4, #3
 8004622:	3201      	adds	r2, #1
 8004624:	6302      	str	r2, [r0, #48]	; 0x30
  RCC_OscInitStruct->PLL.PLLN = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos);
 8004626:	68da      	ldr	r2, [r3, #12]
 8004628:	f3c2 2206 	ubfx	r2, r2, #8, #7
 800462c:	6342      	str	r2, [r0, #52]	; 0x34
  RCC_OscInitStruct->PLL.PLLQ = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U);
 800462e:	68da      	ldr	r2, [r3, #12]
 8004630:	f3c2 5241 	ubfx	r2, r2, #21, #2
 8004634:	3201      	adds	r2, #1
 8004636:	0052      	lsls	r2, r2, #1
 8004638:	63c2      	str	r2, [r0, #60]	; 0x3c
  RCC_OscInitStruct->PLL.PLLR = (uint32_t)((((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> RCC_PLLCFGR_PLLR_Pos) + 1U) << 1U);
 800463a:	68da      	ldr	r2, [r3, #12]
 800463c:	f3c2 6241 	ubfx	r2, r2, #25, #2
 8004640:	3201      	adds	r2, #1
 8004642:	0052      	lsls	r2, r2, #1
 8004644:	6402      	str	r2, [r0, #64]	; 0x40
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
  RCC_OscInitStruct->PLL.PLLP = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos);
#else
  if((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) != RESET)
 8004646:	68db      	ldr	r3, [r3, #12]
 8004648:	039b      	lsls	r3, r3, #14
  {
    RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV17;
 800464a:	bf4c      	ite	mi
 800464c:	2311      	movmi	r3, #17
  }
  else
  {
    RCC_OscInitStruct->PLL.PLLP = RCC_PLLP_DIV7;
 800464e:	2307      	movpl	r3, #7
 8004650:	6383      	str	r3, [r0, #56]	; 0x38
 8004652:	4770      	bx	lr
 8004654:	40021000 	.word	0x40021000

08004658 <HAL_RCC_GetClockConfig>:
  /* Check the parameters */
  assert_param(RCC_ClkInitStruct != NULL);
  assert_param(pFLatency != NULL);

  /* Set all possible values for the Clock type parameter --------------------*/
  RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
 8004658:	230f      	movs	r3, #15
 800465a:	6003      	str	r3, [r0, #0]

  /* Get the SYSCLK configuration --------------------------------------------*/
  RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
 800465c:	4b0b      	ldr	r3, [pc, #44]	; (800468c <HAL_RCC_GetClockConfig+0x34>)
 800465e:	689a      	ldr	r2, [r3, #8]
 8004660:	f002 0203 	and.w	r2, r2, #3
 8004664:	6042      	str	r2, [r0, #4]

  /* Get the HCLK configuration ----------------------------------------------*/
  RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE);
 8004666:	689a      	ldr	r2, [r3, #8]
 8004668:	f002 02f0 	and.w	r2, r2, #240	; 0xf0
 800466c:	6082      	str	r2, [r0, #8]

  /* Get the APB1 configuration ----------------------------------------------*/
  RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1);
 800466e:	689a      	ldr	r2, [r3, #8]
 8004670:	f402 62e0 	and.w	r2, r2, #1792	; 0x700
 8004674:	60c2      	str	r2, [r0, #12]

  /* Get the APB2 configuration ----------------------------------------------*/
  RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3U);
 8004676:	689b      	ldr	r3, [r3, #8]
 8004678:	08db      	lsrs	r3, r3, #3
 800467a:	f403 63e0 	and.w	r3, r3, #1792	; 0x700
 800467e:	6103      	str	r3, [r0, #16]

  /* Get the Flash Wait State (Latency) configuration ------------------------*/
  *pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY);
 8004680:	4b03      	ldr	r3, [pc, #12]	; (8004690 <HAL_RCC_GetClockConfig+0x38>)
 8004682:	681b      	ldr	r3, [r3, #0]
 8004684:	f003 0307 	and.w	r3, r3, #7
 8004688:	600b      	str	r3, [r1, #0]
 800468a:	4770      	bx	lr
 800468c:	40021000 	.word	0x40021000
 8004690:	40022000 	.word	0x40022000

08004694 <HAL_RCC_EnableCSS>:
  * @note   The Clock Security System can only be cleared by reset.
  * @retval None
  */
void HAL_RCC_EnableCSS(void)
{
  SET_BIT(RCC->CR, RCC_CR_CSSON) ;
 8004694:	4a02      	ldr	r2, [pc, #8]	; (80046a0 <HAL_RCC_EnableCSS+0xc>)
 8004696:	6813      	ldr	r3, [r2, #0]
 8004698:	f443 2300 	orr.w	r3, r3, #524288	; 0x80000
 800469c:	6013      	str	r3, [r2, #0]
 800469e:	4770      	bx	lr
 80046a0:	40021000 	.word	0x40021000

080046a4 <HAL_RCC_CSSCallback>:
/**
  * @brief  RCC Clock Security System interrupt callback.
  * @retval none
  */
__weak void HAL_RCC_CSSCallback(void)
{
 80046a4:	4770      	bx	lr
	...

080046a8 <HAL_RCC_NMI_IRQHandler>:
  * @brief Handle the RCC Clock Security System interrupt request.
  * @note This API should be called under the NMI_Handler().
  * @retval None
  */
void HAL_RCC_NMI_IRQHandler(void)
{
 80046a8:	b510      	push	{r4, lr}
  /* Check RCC CSSF interrupt flag  */
  if(__HAL_RCC_GET_IT(RCC_IT_CSS))
 80046aa:	4c05      	ldr	r4, [pc, #20]	; (80046c0 <HAL_RCC_NMI_IRQHandler+0x18>)
 80046ac:	69e3      	ldr	r3, [r4, #28]
 80046ae:	05db      	lsls	r3, r3, #23
 80046b0:	d504      	bpl.n	80046bc <HAL_RCC_NMI_IRQHandler+0x14>
  {
    /* RCC Clock Security System interrupt user callback */
    HAL_RCC_CSSCallback();
 80046b2:	f7ff fff7 	bl	80046a4 <HAL_RCC_CSSCallback>

    /* Clear RCC CSS pending bit */
    __HAL_RCC_CLEAR_IT(RCC_IT_CSS);
 80046b6:	f44f 7380 	mov.w	r3, #256	; 0x100
 80046ba:	6223      	str	r3, [r4, #32]
 80046bc:	bd10      	pop	{r4, pc}
 80046be:	bf00      	nop
 80046c0:	40021000 	.word	0x40021000

080046c4 <RCCEx_PLLSAI1_Config>:
  * @note   PLLSAI1 is temporary disable to apply new parameters
  *
  * @retval HAL status
  */
static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider)
{
 80046c4:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
  assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M));
  assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
  assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut));

  /* Check that PLLSAI1 clock source and divider M can be applied */
  if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE)
 80046c6:	4b46      	ldr	r3, [pc, #280]	; (80047e0 <RCCEx_PLLSAI1_Config+0x11c>)
 80046c8:	68da      	ldr	r2, [r3, #12]
 80046ca:	f012 0f03 	tst.w	r2, #3
  * @note   PLLSAI1 is temporary disable to apply new parameters
  *
  * @retval HAL status
  */
static HAL_StatusTypeDef RCCEx_PLLSAI1_Config(RCC_PLLSAI1InitTypeDef *PllSai1, uint32_t Divider)
{
 80046ce:	4604      	mov	r4, r0
 80046d0:	460e      	mov	r6, r1
 80046d2:	461d      	mov	r5, r3
 80046d4:	6800      	ldr	r0, [r0, #0]
  assert_param(IS_RCC_PLLSAI1M_VALUE(PllSai1->PLLSAI1M));
  assert_param(IS_RCC_PLLSAI1N_VALUE(PllSai1->PLLSAI1N));
  assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PllSai1->PLLSAI1ClockOut));

  /* Check that PLLSAI1 clock source and divider M can be applied */
  if(__HAL_RCC_GET_PLL_OSCSOURCE() != RCC_PLLSOURCE_NONE)
 80046d6:	d00d      	beq.n	80046f4 <RCCEx_PLLSAI1_Config+0x30>
  {
    /* PLL clock source and divider M already set, check that no request for change  */
    if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source)
 80046d8:	68da      	ldr	r2, [r3, #12]
 80046da:	f002 0203 	and.w	r2, r2, #3
 80046de:	4282      	cmp	r2, r0
 80046e0:	d11d      	bne.n	800471e <RCCEx_PLLSAI1_Config+0x5a>
       ||
 80046e2:	b1e2      	cbz	r2, 800471e <RCCEx_PLLSAI1_Config+0x5a>
       (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE)
       ||
       (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U) != PllSai1->PLLSAI1M)
 80046e4:	68db      	ldr	r3, [r3, #12]
  {
    /* PLL clock source and divider M already set, check that no request for change  */
    if((__HAL_RCC_GET_PLL_OSCSOURCE() != PllSai1->PLLSAI1Source)
       ||
       (PllSai1->PLLSAI1Source == RCC_PLLSOURCE_NONE)
       ||
 80046e6:	6862      	ldr	r2, [r4, #4]
 80046e8:	f3c3 1302 	ubfx	r3, r3, #4, #3
 80046ec:	3301      	adds	r3, #1
 80046ee:	4293      	cmp	r3, r2
 80046f0:	d115      	bne.n	800471e <RCCEx_PLLSAI1_Config+0x5a>
 80046f2:	e01f      	b.n	8004734 <RCCEx_PLLSAI1_Config+0x70>
    }
  }
  else
  {
    /* Check PLLSAI1 clock source availability */
    switch(PllSai1->PLLSAI1Source)
 80046f4:	2802      	cmp	r0, #2
 80046f6:	d007      	beq.n	8004708 <RCCEx_PLLSAI1_Config+0x44>
 80046f8:	2803      	cmp	r0, #3
 80046fa:	d009      	beq.n	8004710 <RCCEx_PLLSAI1_Config+0x4c>
 80046fc:	2801      	cmp	r0, #1
 80046fe:	d10e      	bne.n	800471e <RCCEx_PLLSAI1_Config+0x5a>
    {
    case RCC_PLLSOURCE_MSI:
      if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_MSIRDY))
 8004700:	681b      	ldr	r3, [r3, #0]
 8004702:	079f      	lsls	r7, r3, #30
 8004704:	d56a      	bpl.n	80047dc <RCCEx_PLLSAI1_Config+0x118>
 8004706:	e00c      	b.n	8004722 <RCCEx_PLLSAI1_Config+0x5e>
      {
        status = HAL_ERROR;
      }
      break;
    case RCC_PLLSOURCE_HSI:
      if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSIRDY))
 8004708:	681b      	ldr	r3, [r3, #0]
 800470a:	f413 6f80 	tst.w	r3, #1024	; 0x400
 800470e:	e005      	b.n	800471c <RCCEx_PLLSAI1_Config+0x58>
      {
        status = HAL_ERROR;
      }
      break;
    case RCC_PLLSOURCE_HSE:
      if(HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSERDY) && HAL_IS_BIT_CLR(RCC->CR, RCC_CR_HSEBYP))
 8004710:	681a      	ldr	r2, [r3, #0]
 8004712:	0391      	lsls	r1, r2, #14
 8004714:	d405      	bmi.n	8004722 <RCCEx_PLLSAI1_Config+0x5e>
 8004716:	681b      	ldr	r3, [r3, #0]
 8004718:	f413 2f80 	tst.w	r3, #262144	; 0x40000
 800471c:	d101      	bne.n	8004722 <RCCEx_PLLSAI1_Config+0x5e>
 800471e:	2001      	movs	r0, #1
 8004720:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}
    }

    if(status == HAL_OK)
    {
      /* Set PLLSAI1 clock source and divider M */
       MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM, PllSai1->PLLSAI1Source | (PllSai1->PLLSAI1M - 1U) << RCC_PLLCFGR_PLLM_Pos);
 8004722:	68ea      	ldr	r2, [r5, #12]
 8004724:	6863      	ldr	r3, [r4, #4]
 8004726:	f022 0273 	bic.w	r2, r2, #115	; 0x73
 800472a:	3b01      	subs	r3, #1
 800472c:	4310      	orrs	r0, r2
 800472e:	ea40 1003 	orr.w	r0, r0, r3, lsl #4
 8004732:	60e8      	str	r0, [r5, #12]
  }

  if(status == HAL_OK)
  {
    /* Disable the PLLSAI1 */
    __HAL_RCC_PLLSAI1_DISABLE();
 8004734:	682b      	ldr	r3, [r5, #0]
 8004736:	f023 6380 	bic.w	r3, r3, #67108864	; 0x4000000
 800473a:	602b      	str	r3, [r5, #0]

    /* Get Start Tick*/
    tickstart = HAL_GetTick();
 800473c:	f7fc f97c 	bl	8000a38 <HAL_GetTick>
 8004740:	4607      	mov	r7, r0

    /* Wait till PLLSAI1 is ready to be updated */
    while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
 8004742:	682b      	ldr	r3, [r5, #0]
 8004744:	4826      	ldr	r0, [pc, #152]	; (80047e0 <RCCEx_PLLSAI1_Config+0x11c>)
 8004746:	011a      	lsls	r2, r3, #4
 8004748:	d506      	bpl.n	8004758 <RCCEx_PLLSAI1_Config+0x94>
    {
      if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
 800474a:	f7fc f975 	bl	8000a38 <HAL_GetTick>
 800474e:	1bc0      	subs	r0, r0, r7
 8004750:	2802      	cmp	r0, #2
 8004752:	d9f6      	bls.n	8004742 <RCCEx_PLLSAI1_Config+0x7e>
      {
        status = HAL_TIMEOUT;
 8004754:	2003      	movs	r0, #3
 8004756:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}
 8004758:	68a7      	ldr	r7, [r4, #8]
      }
    }

    if(status == HAL_OK)
    {
      if(Divider == DIVIDER_P_UPDATE)
 800475a:	b966      	cbnz	r6, 8004776 <RCCEx_PLLSAI1_Config+0xb2>
        MODIFY_REG(RCC->PLLSAI1CFGR,
                   RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1PDIV,
                   (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
                   (PllSai1->PLLSAI1P << RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos));
#else
        MODIFY_REG(RCC->PLLSAI1CFGR,
 800475c:	6906      	ldr	r6, [r0, #16]
 800475e:	f426 311f 	bic.w	r1, r6, #162816	; 0x27c00
 8004762:	f421 7140 	bic.w	r1, r1, #768	; 0x300
 8004766:	ea41 2307 	orr.w	r3, r1, r7, lsl #8
 800476a:	68e1      	ldr	r1, [r4, #12]
 800476c:	0909      	lsrs	r1, r1, #4
 800476e:	ea43 4141 	orr.w	r1, r3, r1, lsl #17
 8004772:	6101      	str	r1, [r0, #16]
 8004774:	e01c      	b.n	80047b0 <RCCEx_PLLSAI1_Config+0xec>
                   RCC_PLLSAI1CFGR_PLLSAI1N | RCC_PLLSAI1CFGR_PLLSAI1P,
                   (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
                   ((PllSai1->PLLSAI1P >> 4U) << RCC_PLLSAI1CFGR_PLLSAI1P_Pos));
#endif /* RCC_PLLSAI1P_DIV_2_31_SUPPORT */
      }
      else if(Divider == DIVIDER_Q_UPDATE)
 8004776:	2e01      	cmp	r6, #1
 8004778:	d10d      	bne.n	8004796 <RCCEx_PLLSAI1_Config+0xd2>
      {
        assert_param(IS_RCC_PLLSAI1Q_VALUE(PllSai1->PLLSAI1Q));
        /* Configure the PLLSAI1 Division factor Q and Multiplication factor N*/
        MODIFY_REG(RCC->PLLSAI1CFGR,
 800477a:	6922      	ldr	r2, [r4, #16]
 800477c:	6901      	ldr	r1, [r0, #16]
 800477e:	0852      	lsrs	r2, r2, #1
 8004780:	1e53      	subs	r3, r2, #1
 8004782:	f421 02c0 	bic.w	r2, r1, #6291456	; 0x600000
 8004786:	f422 42fe 	bic.w	r2, r2, #32512	; 0x7f00
 800478a:	ea42 2207 	orr.w	r2, r2, r7, lsl #8
 800478e:	ea42 5243 	orr.w	r2, r2, r3, lsl #21
 8004792:	6102      	str	r2, [r0, #16]
 8004794:	e00c      	b.n	80047b0 <RCCEx_PLLSAI1_Config+0xec>
      }
      else
      {
        assert_param(IS_RCC_PLLSAI1R_VALUE(PllSai1->PLLSAI1R));
        /* Configure the PLLSAI1 Division factor R and Multiplication factor N*/
        MODIFY_REG(RCC->PLLSAI1CFGR,
 8004796:	6902      	ldr	r2, [r0, #16]
 8004798:	6966      	ldr	r6, [r4, #20]
 800479a:	f022 63c0 	bic.w	r3, r2, #100663296	; 0x6000000
 800479e:	0876      	lsrs	r6, r6, #1
 80047a0:	f423 43fe 	bic.w	r3, r3, #32512	; 0x7f00
 80047a4:	3e01      	subs	r6, #1
 80047a6:	ea43 2307 	orr.w	r3, r3, r7, lsl #8
 80047aa:	ea43 6346 	orr.w	r3, r3, r6, lsl #25
 80047ae:	6103      	str	r3, [r0, #16]
                   (PllSai1->PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos) |
                   (((PllSai1->PLLSAI1R >> 1U) - 1U) << RCC_PLLSAI1CFGR_PLLSAI1R_Pos));
      }

      /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
      __HAL_RCC_PLLSAI1_ENABLE();
 80047b0:	682b      	ldr	r3, [r5, #0]
 80047b2:	f043 6380 	orr.w	r3, r3, #67108864	; 0x4000000
 80047b6:	602b      	str	r3, [r5, #0]

      /* Get Start Tick*/
      tickstart = HAL_GetTick();
 80047b8:	f7fc f93e 	bl	8000a38 <HAL_GetTick>
 80047bc:	4606      	mov	r6, r0

      /* Wait till PLLSAI1 is ready */
      while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
 80047be:	682b      	ldr	r3, [r5, #0]
 80047c0:	4a07      	ldr	r2, [pc, #28]	; (80047e0 <RCCEx_PLLSAI1_Config+0x11c>)
 80047c2:	011b      	lsls	r3, r3, #4
 80047c4:	d405      	bmi.n	80047d2 <RCCEx_PLLSAI1_Config+0x10e>
      {
        if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
 80047c6:	f7fc f937 	bl	8000a38 <HAL_GetTick>
 80047ca:	1b80      	subs	r0, r0, r6
 80047cc:	2802      	cmp	r0, #2
 80047ce:	d9f6      	bls.n	80047be <RCCEx_PLLSAI1_Config+0xfa>
 80047d0:	e7c0      	b.n	8004754 <RCCEx_PLLSAI1_Config+0x90>
      }

      if(status == HAL_OK)
      {
        /* Configure the PLLSAI1 Clock output(s) */
        __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PllSai1->PLLSAI1ClockOut);
 80047d2:	6911      	ldr	r1, [r2, #16]
 80047d4:	69a3      	ldr	r3, [r4, #24]
 80047d6:	430b      	orrs	r3, r1
 80047d8:	6113      	str	r3, [r2, #16]
 80047da:	2000      	movs	r0, #0
    }
  }

  return status;
#endif
}
 80047dc:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}
 80047de:	bf00      	nop
 80047e0:	40021000 	.word	0x40021000

080047e4 <HAL_RCCEx_PeriphCLKConfig>:
  *         the RTC clock source: in this case the access to Backup domain is enabled.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
 80047e4:	e92d 47f3 	stmdb	sp!, {r0, r1, r4, r5, r6, r7, r8, r9, sl, lr}

  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

  /*-------------------------- SAI1 clock source configuration ---------------------*/
  if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1))
 80047e8:	6805      	ldr	r5, [r0, #0]
 80047ea:	f415 6500 	ands.w	r5, r5, #2048	; 0x800
  *         the RTC clock source: in this case the access to Backup domain is enabled.
  *
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)
{
 80047ee:	4604      	mov	r4, r0

  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));

  /*-------------------------- SAI1 clock source configuration ---------------------*/
  if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI1) == RCC_PERIPHCLK_SAI1))
 80047f0:	d018      	beq.n	8004824 <HAL_RCCEx_PeriphCLKConfig+0x40>
  {
    /* Check the parameters */
    assert_param(IS_RCC_SAI1CLK(PeriphClkInit->Sai1ClockSelection));

    switch(PeriphClkInit->Sai1ClockSelection)
 80047f2:	6e41      	ldr	r1, [r0, #100]	; 0x64
 80047f4:	f5b1 0f00 	cmp.w	r1, #8388608	; 0x800000
 80047f8:	d008      	beq.n	800480c <HAL_RCCEx_PeriphCLKConfig+0x28>
 80047fa:	f5b1 0f40 	cmp.w	r1, #12582912	; 0xc00000
 80047fe:	d005      	beq.n	800480c <HAL_RCCEx_PeriphCLKConfig+0x28>
 8004800:	b979      	cbnz	r1, 8004822 <HAL_RCCEx_PeriphCLKConfig+0x3e>
      /* SAI1 clock source config set later after clock selection check */
      break;

    case RCC_SAI1CLKSOURCE_PLLSAI1:  /* PLLSAI1 is used as clock source for SAI1*/
      /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */
      ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE);
 8004802:	3004      	adds	r0, #4
 8004804:	f7ff ff5e 	bl	80046c4 <RCCEx_PLLSAI1_Config>
    default:
      ret = HAL_ERROR;
      break;
    }

    if(ret == HAL_OK)
 8004808:	4605      	mov	r5, r0
 800480a:	b958      	cbnz	r0, 8004824 <HAL_RCCEx_PeriphCLKConfig+0x40>
    {
      /* Set the source of SAI1 clock*/
      __HAL_RCC_SAI1_CONFIG(PeriphClkInit->Sai1ClockSelection);
 800480c:	49b3      	ldr	r1, [pc, #716]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 800480e:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88
 8004812:	f423 0240 	bic.w	r2, r3, #12582912	; 0xc00000
 8004816:	6e63      	ldr	r3, [r4, #100]	; 0x64
 8004818:	4313      	orrs	r3, r2
 800481a:	f8c1 3088 	str.w	r3, [r1, #136]	; 0x88
 800481e:	2500      	movs	r5, #0
 8004820:	e000      	b.n	8004824 <HAL_RCCEx_PeriphCLKConfig+0x40>
    case RCC_SAI1CLKSOURCE_PIN:      /* External clock is used as source of SAI1 clock*/
      /* SAI1 clock source config set later after clock selection check */
      break;

    default:
      ret = HAL_ERROR;
 8004822:	2501      	movs	r5, #1
  }

#if defined(SAI2)

  /*-------------------------- SAI2 clock source configuration ---------------------*/
  if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2))
 8004824:	6823      	ldr	r3, [r4, #0]
 8004826:	04db      	lsls	r3, r3, #19
 8004828:	d523      	bpl.n	8004872 <HAL_RCCEx_PeriphCLKConfig+0x8e>
  {
    /* Check the parameters */
    assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection));

    switch(PeriphClkInit->Sai2ClockSelection)
 800482a:	6ea1      	ldr	r1, [r4, #104]	; 0x68
 800482c:	f1b1 7f80 	cmp.w	r1, #16777216	; 0x1000000
 8004830:	d012      	beq.n	8004858 <HAL_RCCEx_PeriphCLKConfig+0x74>
 8004832:	d805      	bhi.n	8004840 <HAL_RCCEx_PeriphCLKConfig+0x5c>
 8004834:	b9e1      	cbnz	r1, 8004870 <HAL_RCCEx_PeriphCLKConfig+0x8c>
      /* SAI2 clock source config set later after clock selection check */
      break;

    case RCC_SAI2CLKSOURCE_PLLSAI1: /* PLLSAI1 is used as clock source for SAI2*/
      /* PLLSAI1 input clock, parameters M, N & P configuration and clock output (PLLSAI1ClockOut) */
      ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_P_UPDATE);
 8004836:	1d20      	adds	r0, r4, #4
 8004838:	f7ff ff44 	bl	80046c4 <RCCEx_PLLSAI1_Config>
 800483c:	4606      	mov	r6, r0
      /* SAI2 clock source config set later after clock selection check */
      break;
 800483e:	e00c      	b.n	800485a <HAL_RCCEx_PeriphCLKConfig+0x76>
  if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2))
  {
    /* Check the parameters */
    assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection));

    switch(PeriphClkInit->Sai2ClockSelection)
 8004840:	f1b1 7f00 	cmp.w	r1, #33554432	; 0x2000000
 8004844:	d003      	beq.n	800484e <HAL_RCCEx_PeriphCLKConfig+0x6a>
 8004846:	f1b1 7f40 	cmp.w	r1, #50331648	; 0x3000000
 800484a:	d005      	beq.n	8004858 <HAL_RCCEx_PeriphCLKConfig+0x74>
 800484c:	e010      	b.n	8004870 <HAL_RCCEx_PeriphCLKConfig+0x8c>
    {
    case RCC_SAI2CLKSOURCE_PLL:      /* PLL is used as clock source for SAI2*/
      /* Enable SAI Clock output generated form System PLL . */
      __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_SAI3CLK);
 800484e:	4aa3      	ldr	r2, [pc, #652]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004850:	68d3      	ldr	r3, [r2, #12]
 8004852:	f443 3380 	orr.w	r3, r3, #65536	; 0x10000
 8004856:	60d3      	str	r3, [r2, #12]
  if((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SAI2) == RCC_PERIPHCLK_SAI2))
  {
    /* Check the parameters */
    assert_param(IS_RCC_SAI2CLK(PeriphClkInit->Sai2ClockSelection));

    switch(PeriphClkInit->Sai2ClockSelection)
 8004858:	462e      	mov	r6, r5
    default:
      ret = HAL_ERROR;
      break;
    }

    if(ret == HAL_OK)
 800485a:	b966      	cbnz	r6, 8004876 <HAL_RCCEx_PeriphCLKConfig+0x92>
    {
      /* Set the source of SAI2 clock*/
      __HAL_RCC_SAI2_CONFIG(PeriphClkInit->Sai2ClockSelection);
 800485c:	499f      	ldr	r1, [pc, #636]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 800485e:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88
 8004862:	f023 7240 	bic.w	r2, r3, #50331648	; 0x3000000
 8004866:	6ea3      	ldr	r3, [r4, #104]	; 0x68
 8004868:	4313      	orrs	r3, r2
 800486a:	f8c1 3088 	str.w	r3, [r1, #136]	; 0x88
 800486e:	e003      	b.n	8004878 <HAL_RCCEx_PeriphCLKConfig+0x94>
    case RCC_SAI2CLKSOURCE_PIN:      /* External clock is used as source of SAI2 clock*/
      /* SAI2 clock source config set later after clock selection check */
      break;

    default:
      ret = HAL_ERROR;
 8004870:	2501      	movs	r5, #1
 8004872:	462e      	mov	r6, r5
 8004874:	e000      	b.n	8004878 <HAL_RCCEx_PeriphCLKConfig+0x94>
 8004876:	4635      	mov	r5, r6
    }
  }
#endif /* SAI2 */

  /*-------------------------- RTC clock source configuration ----------------------*/
  if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
 8004878:	6823      	ldr	r3, [r4, #0]
 800487a:	039f      	lsls	r7, r3, #14
 800487c:	d562      	bpl.n	8004944 <HAL_RCCEx_PeriphCLKConfig+0x160>

    /* Check for RTC Parameters used to output RTCCLK */
    assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));

    /* Enable Power Clock */
    if(__HAL_RCC_PWR_IS_CLK_DISABLED())
 800487e:	4f97      	ldr	r7, [pc, #604]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004880:	6dbb      	ldr	r3, [r7, #88]	; 0x58
 8004882:	00d8      	lsls	r0, r3, #3
 8004884:	d40b      	bmi.n	800489e <HAL_RCCEx_PeriphCLKConfig+0xba>
    {
      __HAL_RCC_PWR_CLK_ENABLE();
 8004886:	6dbb      	ldr	r3, [r7, #88]	; 0x58
 8004888:	f043 5380 	orr.w	r3, r3, #268435456	; 0x10000000
 800488c:	65bb      	str	r3, [r7, #88]	; 0x58
 800488e:	6dbb      	ldr	r3, [r7, #88]	; 0x58
 8004890:	f003 5380 	and.w	r3, r3, #268435456	; 0x10000000
 8004894:	9301      	str	r3, [sp, #4]
 8004896:	9b01      	ldr	r3, [sp, #4]
      pwrclkchanged = SET;
 8004898:	f04f 0801 	mov.w	r8, #1
 800489c:	e001      	b.n	80048a2 <HAL_RCCEx_PeriphCLKConfig+0xbe>
#endif /* SAI2 */

  /*-------------------------- RTC clock source configuration ----------------------*/
  if((PeriphClkInit->PeriphClockSelection & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC)
  {
    FlagStatus       pwrclkchanged = RESET;
 800489e:	f04f 0800 	mov.w	r8, #0
      __HAL_RCC_PWR_CLK_ENABLE();
      pwrclkchanged = SET;
    }

    /* Enable write access to Backup domain */
    SET_BIT(PWR->CR1, PWR_CR1_DBP);
 80048a2:	f8df 923c 	ldr.w	r9, [pc, #572]	; 8004ae0 <HAL_RCCEx_PeriphCLKConfig+0x2fc>
 80048a6:	f8d9 3000 	ldr.w	r3, [r9]
 80048aa:	f443 7380 	orr.w	r3, r3, #256	; 0x100
 80048ae:	f8c9 3000 	str.w	r3, [r9]

    /* Wait for Backup domain Write protection disable */
    tickstart = HAL_GetTick();
 80048b2:	f7fc f8c1 	bl	8000a38 <HAL_GetTick>
 80048b6:	4682      	mov	sl, r0

    while((PWR->CR1 & PWR_CR1_DBP) == RESET)
 80048b8:	f8d9 3000 	ldr.w	r3, [r9]
 80048bc:	05d9      	lsls	r1, r3, #23
 80048be:	d406      	bmi.n	80048ce <HAL_RCCEx_PeriphCLKConfig+0xea>
    {
      if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
 80048c0:	f7fc f8ba 	bl	8000a38 <HAL_GetTick>
 80048c4:	ebca 0000 	rsb	r0, sl, r0
 80048c8:	2802      	cmp	r0, #2
 80048ca:	d9f5      	bls.n	80048b8 <HAL_RCCEx_PeriphCLKConfig+0xd4>
 80048cc:	e02f      	b.n	800492e <HAL_RCCEx_PeriphCLKConfig+0x14a>
        ret = HAL_TIMEOUT;
        break;
      }
    }

    if(ret == HAL_OK)
 80048ce:	bb8e      	cbnz	r6, 8004934 <HAL_RCCEx_PeriphCLKConfig+0x150>
    {
      /* Reset the Backup domain only if the RTC Clock source selection is modified from default */
      tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);
 80048d0:	f8d7 3090 	ldr.w	r3, [r7, #144]	; 0x90
 80048d4:	4a81      	ldr	r2, [pc, #516]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)

      if((tmpregister != RCC_RTCCLKSOURCE_NO_CLK) && (tmpregister != PeriphClkInit->RTCClockSelection))
 80048d6:	f413 7340 	ands.w	r3, r3, #768	; 0x300
 80048da:	d015      	beq.n	8004908 <HAL_RCCEx_PeriphCLKConfig+0x124>
 80048dc:	f8d4 1084 	ldr.w	r1, [r4, #132]	; 0x84
 80048e0:	428b      	cmp	r3, r1
 80048e2:	d011      	beq.n	8004908 <HAL_RCCEx_PeriphCLKConfig+0x124>
      {
        /* Store the content of BDCR register before the reset of Backup Domain */
        tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
 80048e4:	f8d2 3090 	ldr.w	r3, [r2, #144]	; 0x90
        /* RTC Clock selection can be changed only if the Backup Domain is reset */
        __HAL_RCC_BACKUPRESET_FORCE();
 80048e8:	f8d2 1090 	ldr.w	r1, [r2, #144]	; 0x90
 80048ec:	f441 3180 	orr.w	r1, r1, #65536	; 0x10000
 80048f0:	f8c2 1090 	str.w	r1, [r2, #144]	; 0x90
        __HAL_RCC_BACKUPRESET_RELEASE();
 80048f4:	f8d2 1090 	ldr.w	r1, [r2, #144]	; 0x90
      tmpregister = READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL);

      if((tmpregister != RCC_RTCCLKSOURCE_NO_CLK) && (tmpregister != PeriphClkInit->RTCClockSelection))
      {
        /* Store the content of BDCR register before the reset of Backup Domain */
        tmpregister = READ_BIT(RCC->BDCR, ~(RCC_BDCR_RTCSEL));
 80048f8:	f423 7340 	bic.w	r3, r3, #768	; 0x300
        /* RTC Clock selection can be changed only if the Backup Domain is reset */
        __HAL_RCC_BACKUPRESET_FORCE();
        __HAL_RCC_BACKUPRESET_RELEASE();
 80048fc:	f421 3180 	bic.w	r1, r1, #65536	; 0x10000
 8004900:	f8c2 1090 	str.w	r1, [r2, #144]	; 0x90
        /* Restore the Content of BDCR register */
        RCC->BDCR = tmpregister;
 8004904:	f8c2 3090 	str.w	r3, [r2, #144]	; 0x90
      }

      /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
      if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON))
 8004908:	07da      	lsls	r2, r3, #31
 800490a:	f140 812c 	bpl.w	8004b66 <HAL_RCCEx_PeriphCLKConfig+0x382>
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 800490e:	f7fc f893 	bl	8000a38 <HAL_GetTick>

        /* Wait till LSE is ready */
        while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
        {
          if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 8004912:	f241 3a88 	movw	sl, #5000	; 0x1388

      /* Wait for LSE reactivation if LSE was enable prior to Backup Domain reset */
      if (HAL_IS_BIT_SET(tmpregister, RCC_BDCR_LSEON))
      {
        /* Get Start Tick*/
        tickstart = HAL_GetTick();
 8004916:	4681      	mov	r9, r0

        /* Wait till LSE is ready */
        while(READ_BIT(RCC->BDCR, RCC_BDCR_LSERDY) == RESET)
 8004918:	f8d7 3090 	ldr.w	r3, [r7, #144]	; 0x90
 800491c:	079b      	lsls	r3, r3, #30
 800491e:	f100 8122 	bmi.w	8004b66 <HAL_RCCEx_PeriphCLKConfig+0x382>
        {
          if((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
 8004922:	f7fc f889 	bl	8000a38 <HAL_GetTick>
 8004926:	ebc9 0000 	rsb	r0, r9, r0
 800492a:	4550      	cmp	r0, sl
 800492c:	d9f4      	bls.n	8004918 <HAL_RCCEx_PeriphCLKConfig+0x134>

    while((PWR->CR1 & PWR_CR1_DBP) == RESET)
    {
      if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
      {
        ret = HAL_TIMEOUT;
 800492e:	2503      	movs	r5, #3
 8004930:	462e      	mov	r6, r5
 8004932:	e000      	b.n	8004936 <HAL_RCCEx_PeriphCLKConfig+0x152>
 8004934:	4635      	mov	r5, r6
      /* set overall return value */
      status = ret;
    }

    /* Restore clock configuration if changed */
    if(pwrclkchanged == SET)
 8004936:	f1b8 0f00 	cmp.w	r8, #0
 800493a:	d003      	beq.n	8004944 <HAL_RCCEx_PeriphCLKConfig+0x160>
    {
      __HAL_RCC_PWR_CLK_DISABLE();
 800493c:	6dbb      	ldr	r3, [r7, #88]	; 0x58
 800493e:	f023 5380 	bic.w	r3, r3, #268435456	; 0x10000000
 8004942:	65bb      	str	r3, [r7, #88]	; 0x58
    }
  }

  /*-------------------------- USART1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART1) == RCC_PERIPHCLK_USART1)
 8004944:	6823      	ldr	r3, [r4, #0]
 8004946:	07d8      	lsls	r0, r3, #31
 8004948:	d508      	bpl.n	800495c <HAL_RCCEx_PeriphCLKConfig+0x178>
  {
    /* Check the parameters */
    assert_param(IS_RCC_USART1CLKSOURCE(PeriphClkInit->Usart1ClockSelection));

    /* Configure the USART1 clock source */
    __HAL_RCC_USART1_CONFIG(PeriphClkInit->Usart1ClockSelection);
 800494a:	4864      	ldr	r0, [pc, #400]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 800494c:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004950:	f022 0103 	bic.w	r1, r2, #3
 8004954:	6ba2      	ldr	r2, [r4, #56]	; 0x38
 8004956:	430a      	orrs	r2, r1
 8004958:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

  /*-------------------------- USART2 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART2) == RCC_PERIPHCLK_USART2)
 800495c:	0799      	lsls	r1, r3, #30
 800495e:	d508      	bpl.n	8004972 <HAL_RCCEx_PeriphCLKConfig+0x18e>
  {
    /* Check the parameters */
    assert_param(IS_RCC_USART2CLKSOURCE(PeriphClkInit->Usart2ClockSelection));

    /* Configure the USART2 clock source */
    __HAL_RCC_USART2_CONFIG(PeriphClkInit->Usart2ClockSelection);
 8004960:	485e      	ldr	r0, [pc, #376]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004962:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004966:	f022 010c 	bic.w	r1, r2, #12
 800496a:	6be2      	ldr	r2, [r4, #60]	; 0x3c
 800496c:	430a      	orrs	r2, r1
 800496e:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

#if defined(USART3)

  /*-------------------------- USART3 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USART3) == RCC_PERIPHCLK_USART3)
 8004972:	075a      	lsls	r2, r3, #29
 8004974:	d508      	bpl.n	8004988 <HAL_RCCEx_PeriphCLKConfig+0x1a4>
  {
    /* Check the parameters */
    assert_param(IS_RCC_USART3CLKSOURCE(PeriphClkInit->Usart3ClockSelection));

    /* Configure the USART3 clock source */
    __HAL_RCC_USART3_CONFIG(PeriphClkInit->Usart3ClockSelection);
 8004976:	4859      	ldr	r0, [pc, #356]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004978:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 800497c:	f022 0130 	bic.w	r1, r2, #48	; 0x30
 8004980:	6c22      	ldr	r2, [r4, #64]	; 0x40
 8004982:	430a      	orrs	r2, r1
 8004984:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
#endif /* USART3 */

#if defined(UART4)

  /*-------------------------- UART4 clock source configuration --------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART4) == RCC_PERIPHCLK_UART4)
 8004988:	071f      	lsls	r7, r3, #28
 800498a:	d508      	bpl.n	800499e <HAL_RCCEx_PeriphCLKConfig+0x1ba>
  {
    /* Check the parameters */
    assert_param(IS_RCC_UART4CLKSOURCE(PeriphClkInit->Uart4ClockSelection));

    /* Configure the UART4 clock source */
    __HAL_RCC_UART4_CONFIG(PeriphClkInit->Uart4ClockSelection);
 800498c:	4853      	ldr	r0, [pc, #332]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 800498e:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004992:	f022 01c0 	bic.w	r1, r2, #192	; 0xc0
 8004996:	6c62      	ldr	r2, [r4, #68]	; 0x44
 8004998:	430a      	orrs	r2, r1
 800499a:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
#endif /* UART4 */

#if defined(UART5)

  /*-------------------------- UART5 clock source configuration --------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_UART5) == RCC_PERIPHCLK_UART5)
 800499e:	06d8      	lsls	r0, r3, #27
 80049a0:	d508      	bpl.n	80049b4 <HAL_RCCEx_PeriphCLKConfig+0x1d0>
  {
    /* Check the parameters */
    assert_param(IS_RCC_UART5CLKSOURCE(PeriphClkInit->Uart5ClockSelection));

    /* Configure the UART5 clock source */
    __HAL_RCC_UART5_CONFIG(PeriphClkInit->Uart5ClockSelection);
 80049a2:	484e      	ldr	r0, [pc, #312]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 80049a4:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 80049a8:	f422 7140 	bic.w	r1, r2, #768	; 0x300
 80049ac:	6ca2      	ldr	r2, [r4, #72]	; 0x48
 80049ae:	430a      	orrs	r2, r1
 80049b0:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

#endif /* UART5 */

  /*-------------------------- LPUART1 clock source configuration ------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPUART1) == RCC_PERIPHCLK_LPUART1)
 80049b4:	0699      	lsls	r1, r3, #26
 80049b6:	d508      	bpl.n	80049ca <HAL_RCCEx_PeriphCLKConfig+0x1e6>
  {
    /* Check the parameters */
    assert_param(IS_RCC_LPUART1CLKSOURCE(PeriphClkInit->Lpuart1ClockSelection));

    /* Configure the LPUAR1 clock source */
    __HAL_RCC_LPUART1_CONFIG(PeriphClkInit->Lpuart1ClockSelection);
 80049b8:	4848      	ldr	r0, [pc, #288]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 80049ba:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 80049be:	f422 6140 	bic.w	r1, r2, #3072	; 0xc00
 80049c2:	6ce2      	ldr	r2, [r4, #76]	; 0x4c
 80049c4:	430a      	orrs	r2, r1
 80049c6:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

  /*-------------------------- LPTIM1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM1) == (RCC_PERIPHCLK_LPTIM1))
 80049ca:	059a      	lsls	r2, r3, #22
 80049cc:	d508      	bpl.n	80049e0 <HAL_RCCEx_PeriphCLKConfig+0x1fc>
  {
    assert_param(IS_RCC_LPTIM1CLK(PeriphClkInit->Lptim1ClockSelection));
    __HAL_RCC_LPTIM1_CONFIG(PeriphClkInit->Lptim1ClockSelection);
 80049ce:	4843      	ldr	r0, [pc, #268]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 80049d0:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 80049d4:	f422 2140 	bic.w	r1, r2, #786432	; 0xc0000
 80049d8:	6de2      	ldr	r2, [r4, #92]	; 0x5c
 80049da:	430a      	orrs	r2, r1
 80049dc:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

  /*-------------------------- LPTIM2 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_LPTIM2) == (RCC_PERIPHCLK_LPTIM2))
 80049e0:	055f      	lsls	r7, r3, #21
 80049e2:	d508      	bpl.n	80049f6 <HAL_RCCEx_PeriphCLKConfig+0x212>
  {
    assert_param(IS_RCC_LPTIM2CLK(PeriphClkInit->Lptim2ClockSelection));
    __HAL_RCC_LPTIM2_CONFIG(PeriphClkInit->Lptim2ClockSelection);
 80049e4:	483d      	ldr	r0, [pc, #244]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 80049e6:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 80049ea:	f422 1140 	bic.w	r1, r2, #3145728	; 0x300000
 80049ee:	6e22      	ldr	r2, [r4, #96]	; 0x60
 80049f0:	430a      	orrs	r2, r1
 80049f2:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

  /*-------------------------- I2C1 clock source configuration ---------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C1) == RCC_PERIPHCLK_I2C1)
 80049f6:	0658      	lsls	r0, r3, #25
 80049f8:	d508      	bpl.n	8004a0c <HAL_RCCEx_PeriphCLKConfig+0x228>
  {
    /* Check the parameters */
    assert_param(IS_RCC_I2C1CLKSOURCE(PeriphClkInit->I2c1ClockSelection));

    /* Configure the I2C1 clock source */
    __HAL_RCC_I2C1_CONFIG(PeriphClkInit->I2c1ClockSelection);
 80049fa:	4838      	ldr	r0, [pc, #224]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 80049fc:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004a00:	f422 5140 	bic.w	r1, r2, #12288	; 0x3000
 8004a04:	6d22      	ldr	r2, [r4, #80]	; 0x50
 8004a06:	430a      	orrs	r2, r1
 8004a08:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

#if defined(I2C2)

  /*-------------------------- I2C2 clock source configuration ---------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C2) == RCC_PERIPHCLK_I2C2)
 8004a0c:	0619      	lsls	r1, r3, #24
 8004a0e:	d508      	bpl.n	8004a22 <HAL_RCCEx_PeriphCLKConfig+0x23e>
  {
    /* Check the parameters */
    assert_param(IS_RCC_I2C2CLKSOURCE(PeriphClkInit->I2c2ClockSelection));

    /* Configure the I2C2 clock source */
    __HAL_RCC_I2C2_CONFIG(PeriphClkInit->I2c2ClockSelection);
 8004a10:	4832      	ldr	r0, [pc, #200]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004a12:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004a16:	f422 4140 	bic.w	r1, r2, #49152	; 0xc000
 8004a1a:	6d62      	ldr	r2, [r4, #84]	; 0x54
 8004a1c:	430a      	orrs	r2, r1
 8004a1e:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
  }

#endif /* I2C2 */

  /*-------------------------- I2C3 clock source configuration ---------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2C3) == RCC_PERIPHCLK_I2C3)
 8004a22:	05da      	lsls	r2, r3, #23
 8004a24:	d508      	bpl.n	8004a38 <HAL_RCCEx_PeriphCLKConfig+0x254>
  {
    /* Check the parameters */
    assert_param(IS_RCC_I2C3CLKSOURCE(PeriphClkInit->I2c3ClockSelection));

    /* Configure the I2C3 clock source */
    __HAL_RCC_I2C3_CONFIG(PeriphClkInit->I2c3ClockSelection);
 8004a26:	482d      	ldr	r0, [pc, #180]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004a28:	f8d0 2088 	ldr.w	r2, [r0, #136]	; 0x88
 8004a2c:	f422 3140 	bic.w	r1, r2, #196608	; 0x30000
 8004a30:	6da2      	ldr	r2, [r4, #88]	; 0x58
 8004a32:	430a      	orrs	r2, r1
 8004a34:	f8c0 2088 	str.w	r2, [r0, #136]	; 0x88
#endif /* I2C4 */

#if defined(USB_OTG_FS) || defined(USB)

  /*-------------------------- USB clock source configuration ----------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB))
 8004a38:	049b      	lsls	r3, r3, #18
 8004a3a:	d51b      	bpl.n	8004a74 <HAL_RCCEx_PeriphCLKConfig+0x290>
  {
    assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
    __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
 8004a3c:	4a27      	ldr	r2, [pc, #156]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004a3e:	6ee1      	ldr	r1, [r4, #108]	; 0x6c
 8004a40:	f8d2 3088 	ldr.w	r3, [r2, #136]	; 0x88
 8004a44:	f023 6340 	bic.w	r3, r3, #201326592	; 0xc000000
 8004a48:	430b      	orrs	r3, r1

    if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL)
 8004a4a:	f1b1 6f00 	cmp.w	r1, #134217728	; 0x8000000

  /*-------------------------- USB clock source configuration ----------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == (RCC_PERIPHCLK_USB))
  {
    assert_param(IS_RCC_USBCLKSOURCE(PeriphClkInit->UsbClockSelection));
    __HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
 8004a4e:	f8c2 3088 	str.w	r3, [r2, #136]	; 0x88

    if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLL)
 8004a52:	d104      	bne.n	8004a5e <HAL_RCCEx_PeriphCLKConfig+0x27a>
    {
      /* Enable PLL48M1CLK output */
      __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
 8004a54:	68d3      	ldr	r3, [r2, #12]
 8004a56:	f443 1380 	orr.w	r3, r3, #1048576	; 0x100000
 8004a5a:	60d3      	str	r3, [r2, #12]
 8004a5c:	e00a      	b.n	8004a74 <HAL_RCCEx_PeriphCLKConfig+0x290>
    }
    else
    {
      if(PeriphClkInit->UsbClockSelection == RCC_USBCLKSOURCE_PLLSAI1)
 8004a5e:	f1b1 6f80 	cmp.w	r1, #67108864	; 0x4000000
 8004a62:	d107      	bne.n	8004a74 <HAL_RCCEx_PeriphCLKConfig+0x290>
      {
        /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
        ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
 8004a64:	2101      	movs	r1, #1
 8004a66:	1d20      	adds	r0, r4, #4
 8004a68:	f7ff fe2c 	bl	80046c4 <RCCEx_PLLSAI1_Config>

        if(ret != HAL_OK)
 8004a6c:	4606      	mov	r6, r0
 8004a6e:	2800      	cmp	r0, #0
 8004a70:	bf18      	it	ne
 8004a72:	4605      	movne	r5, r0
#endif /* USB_OTG_FS || USB */

#if defined(SDMMC1)

  /*-------------------------- SDMMC1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1))
 8004a74:	6823      	ldr	r3, [r4, #0]
 8004a76:	031f      	lsls	r7, r3, #12
 8004a78:	d51b      	bpl.n	8004ab2 <HAL_RCCEx_PeriphCLKConfig+0x2ce>
  {
    assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection));
    __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection);
 8004a7a:	4a18      	ldr	r2, [pc, #96]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004a7c:	6f21      	ldr	r1, [r4, #112]	; 0x70
 8004a7e:	f8d2 3088 	ldr.w	r3, [r2, #136]	; 0x88
 8004a82:	f023 6340 	bic.w	r3, r3, #201326592	; 0xc000000
 8004a86:	430b      	orrs	r3, r1

    if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL)
 8004a88:	f1b1 6f00 	cmp.w	r1, #134217728	; 0x8000000

  /*-------------------------- SDMMC1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SDMMC1) == (RCC_PERIPHCLK_SDMMC1))
  {
    assert_param(IS_RCC_SDMMC1CLKSOURCE(PeriphClkInit->Sdmmc1ClockSelection));
    __HAL_RCC_SDMMC1_CONFIG(PeriphClkInit->Sdmmc1ClockSelection);
 8004a8c:	f8c2 3088 	str.w	r3, [r2, #136]	; 0x88

    if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLL)
 8004a90:	d104      	bne.n	8004a9c <HAL_RCCEx_PeriphCLKConfig+0x2b8>
    {
      /* Enable PLL48M1CLK output */
      __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
 8004a92:	68d3      	ldr	r3, [r2, #12]
 8004a94:	f443 1380 	orr.w	r3, r3, #1048576	; 0x100000
 8004a98:	60d3      	str	r3, [r2, #12]
 8004a9a:	e00a      	b.n	8004ab2 <HAL_RCCEx_PeriphCLKConfig+0x2ce>
    }
    else if(PeriphClkInit->Sdmmc1ClockSelection == RCC_SDMMC1CLKSOURCE_PLLSAI1)
 8004a9c:	f1b1 6f80 	cmp.w	r1, #67108864	; 0x4000000
 8004aa0:	d107      	bne.n	8004ab2 <HAL_RCCEx_PeriphCLKConfig+0x2ce>
    {
      /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
      ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
 8004aa2:	2101      	movs	r1, #1
 8004aa4:	1d20      	adds	r0, r4, #4
 8004aa6:	f7ff fe0d 	bl	80046c4 <RCCEx_PLLSAI1_Config>

      if(ret != HAL_OK)
 8004aaa:	4606      	mov	r6, r0
 8004aac:	2800      	cmp	r0, #0
 8004aae:	bf18      	it	ne
 8004ab0:	4605      	movne	r5, r0
  }

#endif /* SDMMC1 */

  /*-------------------------- RNG clock source configuration ----------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG))
 8004ab2:	6823      	ldr	r3, [r4, #0]
 8004ab4:	0358      	lsls	r0, r3, #13
 8004ab6:	d520      	bpl.n	8004afa <HAL_RCCEx_PeriphCLKConfig+0x316>
  {
    assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection));
    __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
 8004ab8:	4a08      	ldr	r2, [pc, #32]	; (8004adc <HAL_RCCEx_PeriphCLKConfig+0x2f8>)
 8004aba:	6f61      	ldr	r1, [r4, #116]	; 0x74
 8004abc:	f8d2 3088 	ldr.w	r3, [r2, #136]	; 0x88
 8004ac0:	f023 6340 	bic.w	r3, r3, #201326592	; 0xc000000
 8004ac4:	430b      	orrs	r3, r1

    if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL)
 8004ac6:	f1b1 6f00 	cmp.w	r1, #134217728	; 0x8000000

  /*-------------------------- RNG clock source configuration ----------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RNG) == (RCC_PERIPHCLK_RNG))
  {
    assert_param(IS_RCC_RNGCLKSOURCE(PeriphClkInit->RngClockSelection));
    __HAL_RCC_RNG_CONFIG(PeriphClkInit->RngClockSelection);
 8004aca:	f8c2 3088 	str.w	r3, [r2, #136]	; 0x88

    if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLL)
 8004ace:	d109      	bne.n	8004ae4 <HAL_RCCEx_PeriphCLKConfig+0x300>
    {
      /* Enable PLL48M1CLK output */
      __HAL_RCC_PLLCLKOUT_ENABLE(RCC_PLL_48M1CLK);
 8004ad0:	68d3      	ldr	r3, [r2, #12]
 8004ad2:	f443 1380 	orr.w	r3, r3, #1048576	; 0x100000
 8004ad6:	60d3      	str	r3, [r2, #12]
 8004ad8:	e00f      	b.n	8004afa <HAL_RCCEx_PeriphCLKConfig+0x316>
 8004ada:	bf00      	nop
 8004adc:	40021000 	.word	0x40021000
 8004ae0:	40007000 	.word	0x40007000
    }
    else if(PeriphClkInit->RngClockSelection == RCC_RNGCLKSOURCE_PLLSAI1)
 8004ae4:	f1b1 6f80 	cmp.w	r1, #67108864	; 0x4000000
 8004ae8:	d107      	bne.n	8004afa <HAL_RCCEx_PeriphCLKConfig+0x316>
    {
      /* PLLSAI1 input clock, parameters M, N & Q configuration and clock output (PLLSAI1ClockOut) */
      ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_Q_UPDATE);
 8004aea:	2101      	movs	r1, #1
 8004aec:	1d20      	adds	r0, r4, #4
 8004aee:	f7ff fde9 	bl	80046c4 <RCCEx_PLLSAI1_Config>

      if(ret != HAL_OK)
 8004af2:	4606      	mov	r6, r0
 8004af4:	2800      	cmp	r0, #0
 8004af6:	bf18      	it	ne
 8004af8:	4605      	movne	r5, r0
      }
    }
  }

  /*-------------------------- ADC clock source configuration ----------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
 8004afa:	6823      	ldr	r3, [r4, #0]
 8004afc:	0459      	lsls	r1, r3, #17
 8004afe:	d519      	bpl.n	8004b34 <HAL_RCCEx_PeriphCLKConfig+0x350>
  {
    /* Check the parameters */
    assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));

    /* Configure the ADC interface clock source */
    __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
 8004b00:	4920      	ldr	r1, [pc, #128]	; (8004b84 <HAL_RCCEx_PeriphCLKConfig+0x3a0>)
 8004b02:	6fa2      	ldr	r2, [r4, #120]	; 0x78
 8004b04:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88
 8004b08:	f023 5340 	bic.w	r3, r3, #805306368	; 0x30000000
 8004b0c:	4313      	orrs	r3, r2

    if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1)
 8004b0e:	f1b2 5f80 	cmp.w	r2, #268435456	; 0x10000000
  {
    /* Check the parameters */
    assert_param(IS_RCC_ADCCLKSOURCE(PeriphClkInit->AdcClockSelection));

    /* Configure the ADC interface clock source */
    __HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
 8004b12:	f8c1 3088 	str.w	r3, [r1, #136]	; 0x88

    if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI1)
 8004b16:	d107      	bne.n	8004b28 <HAL_RCCEx_PeriphCLKConfig+0x344>
    {
      /* PLLSAI1 input clock, parameters M, N & R configuration and clock output (PLLSAI1ClockOut) */
      ret = RCCEx_PLLSAI1_Config(&(PeriphClkInit->PLLSAI1), DIVIDER_R_UPDATE);
 8004b18:	2102      	movs	r1, #2
 8004b1a:	1d20      	adds	r0, r4, #4
 8004b1c:	f7ff fdd2 	bl	80046c4 <RCCEx_PLLSAI1_Config>

      if(ret != HAL_OK)
 8004b20:	2800      	cmp	r0, #0
 8004b22:	bf18      	it	ne
 8004b24:	4605      	movne	r5, r0
 8004b26:	e005      	b.n	8004b34 <HAL_RCCEx_PeriphCLKConfig+0x350>
      }
    }

#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx)

    else if(PeriphClkInit->AdcClockSelection == RCC_ADCCLKSOURCE_PLLSAI2)
 8004b28:	f1b2 5f00 	cmp.w	r2, #536870912	; 0x20000000
 8004b2c:	d102      	bne.n	8004b34 <HAL_RCCEx_PeriphCLKConfig+0x350>
      /* PLLSAI2 input clock, parameters M, N & R configuration and clock output (PLLSAI2ClockOut) */
#if defined(RCC_PLLSAI2_SUPPORT)
      ret = RCCEx_PLLSAI2_Config(&(PeriphClkInit->PLLSAI2), DIVIDER_R_UPDATE);
#endif

      if(ret != HAL_OK)
 8004b2e:	2e00      	cmp	r6, #0
 8004b30:	bf18      	it	ne
 8004b32:	4635      	movne	r5, r6
  }

#if defined(SWPMI1)

  /*-------------------------- SWPMI1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_SWPMI1) == RCC_PERIPHCLK_SWPMI1)
 8004b34:	6821      	ldr	r1, [r4, #0]
 8004b36:	040a      	lsls	r2, r1, #16
 8004b38:	d508      	bpl.n	8004b4c <HAL_RCCEx_PeriphCLKConfig+0x368>
  {
    /* Check the parameters */
    assert_param(IS_RCC_SWPMI1CLKSOURCE(PeriphClkInit->Swpmi1ClockSelection));

    /* Configure the SWPMI1 clock source */
    __HAL_RCC_SWPMI1_CONFIG(PeriphClkInit->Swpmi1ClockSelection);
 8004b3a:	4812      	ldr	r0, [pc, #72]	; (8004b84 <HAL_RCCEx_PeriphCLKConfig+0x3a0>)
 8004b3c:	f8d0 3088 	ldr.w	r3, [r0, #136]	; 0x88
 8004b40:	f023 4280 	bic.w	r2, r3, #1073741824	; 0x40000000
 8004b44:	6fe3      	ldr	r3, [r4, #124]	; 0x7c
 8004b46:	4313      	orrs	r3, r2
 8004b48:	f8c0 3088 	str.w	r3, [r0, #136]	; 0x88
#endif /* SWPMI1 */

#if defined(DFSDM1_Filter0)

  /*-------------------------- DFSDM1 clock source configuration -------------------*/
  if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_DFSDM1) == RCC_PERIPHCLK_DFSDM1)
 8004b4c:	03cb      	lsls	r3, r1, #15
 8004b4e:	d514      	bpl.n	8004b7a <HAL_RCCEx_PeriphCLKConfig+0x396>
  {
    /* Check the parameters */
    assert_param(IS_RCC_DFSDM1CLKSOURCE(PeriphClkInit->Dfsdm1ClockSelection));

    /* Configure the DFSDM1 interface clock source */
    __HAL_RCC_DFSDM1_CONFIG(PeriphClkInit->Dfsdm1ClockSelection);
 8004b50:	490c      	ldr	r1, [pc, #48]	; (8004b84 <HAL_RCCEx_PeriphCLKConfig+0x3a0>)
 8004b52:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88
 8004b56:	f023 4200 	bic.w	r2, r3, #2147483648	; 0x80000000
 8004b5a:	f8d4 3080 	ldr.w	r3, [r4, #128]	; 0x80
 8004b5e:	4313      	orrs	r3, r2
 8004b60:	f8c1 3088 	str.w	r3, [r1, #136]	; 0x88
  }

#endif /* DFSDM1_Filter0 */

  return status;
 8004b64:	e009      	b.n	8004b7a <HAL_RCCEx_PeriphCLKConfig+0x396>
      }

      if(ret == HAL_OK)
      {
        /* Apply new RTC clock source selection */
        __HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
 8004b66:	f8d7 3090 	ldr.w	r3, [r7, #144]	; 0x90
 8004b6a:	f423 7240 	bic.w	r2, r3, #768	; 0x300
 8004b6e:	f8d4 3084 	ldr.w	r3, [r4, #132]	; 0x84
 8004b72:	4313      	orrs	r3, r2
 8004b74:	f8c7 3090 	str.w	r3, [r7, #144]	; 0x90
 8004b78:	e6dd      	b.n	8004936 <HAL_RCCEx_PeriphCLKConfig+0x152>
  }

#endif /* DFSDM1_Filter0 */

  return status;
}
 8004b7a:	4628      	mov	r0, r5
 8004b7c:	b002      	add	sp, #8
 8004b7e:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
 8004b82:	bf00      	nop
 8004b84:	40021000 	.word	0x40021000

08004b88 <HAL_RCCEx_GetPeriphCLKConfig>:
                                        RCC_PERIPHCLK_SDMMC1  | RCC_PERIPHCLK_RNG    | RCC_PERIPHCLK_ADC    | RCC_PERIPHCLK_SWPMI1 | RCC_PERIPHCLK_DFSDM1 | \
                                        RCC_PERIPHCLK_RTC ;

#elif defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx)

  PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_USART1  | RCC_PERIPHCLK_USART2 | RCC_PERIPHCLK_USART3 | RCC_PERIPHCLK_UART4  | RCC_PERIPHCLK_UART5  | \
 8004b88:	4b44      	ldr	r3, [pc, #272]	; (8004c9c <HAL_RCCEx_GetPeriphCLKConfig+0x114>)
 8004b8a:	6003      	str	r3, [r0, #0]

#endif /* STM32L431xx */

  /* Get the PLLSAI1 Clock configuration -----------------------------------------------*/

  PeriphClkInit->PLLSAI1.PLLSAI1Source = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> RCC_PLLCFGR_PLLSRC_Pos);
 8004b8c:	4b44      	ldr	r3, [pc, #272]	; (8004ca0 <HAL_RCCEx_GetPeriphCLKConfig+0x118>)
 8004b8e:	68da      	ldr	r2, [r3, #12]
 8004b90:	f002 0203 	and.w	r2, r2, #3
 8004b94:	6042      	str	r2, [r0, #4]
  PeriphClkInit->PLLSAI1.PLLSAI1M = (uint32_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U;
 8004b96:	68da      	ldr	r2, [r3, #12]
 8004b98:	f3c2 1202 	ubfx	r2, r2, #4, #3
 8004b9c:	3201      	adds	r2, #1
 8004b9e:	6082      	str	r2, [r0, #8]
  PeriphClkInit->PLLSAI1.PLLSAI1N = (uint32_t)((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos);
 8004ba0:	691a      	ldr	r2, [r3, #16]
 8004ba2:	f3c2 2206 	ubfx	r2, r2, #8, #7
 8004ba6:	60c2      	str	r2, [r0, #12]
  PeriphClkInit->PLLSAI1.PLLSAI1P = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1P) >> RCC_PLLSAI1CFGR_PLLSAI1P_Pos) << 4U) + 7U;
 8004ba8:	691a      	ldr	r2, [r3, #16]
 8004baa:	0b52      	lsrs	r2, r2, #13
 8004bac:	f002 0210 	and.w	r2, r2, #16
 8004bb0:	3207      	adds	r2, #7
 8004bb2:	6102      	str	r2, [r0, #16]
  PeriphClkInit->PLLSAI1.PLLSAI1Q = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos)+1U) * 2U;
 8004bb4:	691a      	ldr	r2, [r3, #16]
 8004bb6:	f3c2 5241 	ubfx	r2, r2, #21, #2
 8004bba:	3201      	adds	r2, #1
 8004bbc:	0052      	lsls	r2, r2, #1
 8004bbe:	6142      	str	r2, [r0, #20]
  PeriphClkInit->PLLSAI1.PLLSAI1R = (uint32_t)(((RCC->PLLSAI1CFGR & RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos)+1U) * 2U;
 8004bc0:	691a      	ldr	r2, [r3, #16]
 8004bc2:	f3c2 6241 	ubfx	r2, r2, #25, #2
 8004bc6:	3201      	adds	r2, #1
 8004bc8:	0052      	lsls	r2, r2, #1
 8004bca:	6182      	str	r2, [r0, #24]
   PeriphClkInit->PLLSAI2.PLLSAI2R = (uint32_t)(((RCC->PLLSAI2CFGR & RCC_PLLSAI2CFGR_PLLSAI2R)>> RCC_PLLSAI2CFGR_PLLSAI2R_Pos)+1U) * 2U;

#endif /* RCC_PLLSAI2_SUPPORT */

  /* Get the USART1 clock source ---------------------------------------------*/
  PeriphClkInit->Usart1ClockSelection  = __HAL_RCC_GET_USART1_SOURCE();
 8004bcc:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004bd0:	f002 0203 	and.w	r2, r2, #3
 8004bd4:	6382      	str	r2, [r0, #56]	; 0x38
  /* Get the USART2 clock source ---------------------------------------------*/
  PeriphClkInit->Usart2ClockSelection  = __HAL_RCC_GET_USART2_SOURCE();
 8004bd6:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004bda:	f002 020c 	and.w	r2, r2, #12
 8004bde:	63c2      	str	r2, [r0, #60]	; 0x3c

#if defined(USART3)
  /* Get the USART3 clock source ---------------------------------------------*/
  PeriphClkInit->Usart3ClockSelection  = __HAL_RCC_GET_USART3_SOURCE();
 8004be0:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004be4:	f002 0230 	and.w	r2, r2, #48	; 0x30
 8004be8:	6402      	str	r2, [r0, #64]	; 0x40
#endif /* USART3 */

#if defined(UART4)
  /* Get the UART4 clock source ----------------------------------------------*/
  PeriphClkInit->Uart4ClockSelection   = __HAL_RCC_GET_UART4_SOURCE();
 8004bea:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004bee:	f002 02c0 	and.w	r2, r2, #192	; 0xc0
 8004bf2:	6442      	str	r2, [r0, #68]	; 0x44
#endif /* UART4 */

#if defined(UART5)
  /* Get the UART5 clock source ----------------------------------------------*/
  PeriphClkInit->Uart5ClockSelection   = __HAL_RCC_GET_UART5_SOURCE();
 8004bf4:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004bf8:	f402 7240 	and.w	r2, r2, #768	; 0x300
 8004bfc:	6482      	str	r2, [r0, #72]	; 0x48
#endif /* UART5 */

  /* Get the LPUART1 clock source --------------------------------------------*/
  PeriphClkInit->Lpuart1ClockSelection = __HAL_RCC_GET_LPUART1_SOURCE();
 8004bfe:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c02:	f402 6240 	and.w	r2, r2, #3072	; 0xc00
 8004c06:	64c2      	str	r2, [r0, #76]	; 0x4c

  /* Get the I2C1 clock source -----------------------------------------------*/
  PeriphClkInit->I2c1ClockSelection    = __HAL_RCC_GET_I2C1_SOURCE();
 8004c08:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c0c:	f402 5240 	and.w	r2, r2, #12288	; 0x3000
 8004c10:	6502      	str	r2, [r0, #80]	; 0x50

#if defined(I2C2)
   /* Get the I2C2 clock source ----------------------------------------------*/
  PeriphClkInit->I2c2ClockSelection    = __HAL_RCC_GET_I2C2_SOURCE();
 8004c12:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c16:	f402 4240 	and.w	r2, r2, #49152	; 0xc000
 8004c1a:	6542      	str	r2, [r0, #84]	; 0x54
#endif /* I2C2 */

  /* Get the I2C3 clock source -----------------------------------------------*/
  PeriphClkInit->I2c3ClockSelection    = __HAL_RCC_GET_I2C3_SOURCE();
 8004c1c:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c20:	f402 3240 	and.w	r2, r2, #196608	; 0x30000
 8004c24:	6582      	str	r2, [r0, #88]	; 0x58
  /* Get the I2C4 clock source -----------------------------------------------*/
  PeriphClkInit->I2c4ClockSelection    = __HAL_RCC_GET_I2C4_SOURCE();
#endif /* I2C4 */

  /* Get the LPTIM1 clock source ---------------------------------------------*/
  PeriphClkInit->Lptim1ClockSelection  = __HAL_RCC_GET_LPTIM1_SOURCE();
 8004c26:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c2a:	f402 2240 	and.w	r2, r2, #786432	; 0xc0000
 8004c2e:	65c2      	str	r2, [r0, #92]	; 0x5c

  /* Get the LPTIM2 clock source ---------------------------------------------*/
  PeriphClkInit->Lptim2ClockSelection  = __HAL_RCC_GET_LPTIM2_SOURCE();
 8004c30:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c34:	f402 1240 	and.w	r2, r2, #3145728	; 0x300000
 8004c38:	6602      	str	r2, [r0, #96]	; 0x60

  /* Get the SAI1 clock source -----------------------------------------------*/
  PeriphClkInit->Sai1ClockSelection    = __HAL_RCC_GET_SAI1_SOURCE();
 8004c3a:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c3e:	f402 0240 	and.w	r2, r2, #12582912	; 0xc00000
 8004c42:	6642      	str	r2, [r0, #100]	; 0x64

#if defined(SAI2)
  /* Get the SAI2 clock source -----------------------------------------------*/
  PeriphClkInit->Sai2ClockSelection    = __HAL_RCC_GET_SAI2_SOURCE();
 8004c44:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c48:	f002 7240 	and.w	r2, r2, #50331648	; 0x3000000
 8004c4c:	6682      	str	r2, [r0, #104]	; 0x68
#endif /* SAI2 */

  /* Get the RTC clock source ------------------------------------------------*/
  PeriphClkInit->RTCClockSelection     = __HAL_RCC_GET_RTC_SOURCE();
 8004c4e:	f8d3 2090 	ldr.w	r2, [r3, #144]	; 0x90
 8004c52:	f402 7240 	and.w	r2, r2, #768	; 0x300
 8004c56:	f8c0 2084 	str.w	r2, [r0, #132]	; 0x84

#if defined(USB_OTG_FS) || defined(USB)
  /* Get the USB clock source ------------------------------------------------*/
  PeriphClkInit->UsbClockSelection   = __HAL_RCC_GET_USB_SOURCE();
 8004c5a:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c5e:	f002 6240 	and.w	r2, r2, #201326592	; 0xc000000
 8004c62:	66c2      	str	r2, [r0, #108]	; 0x6c
#endif /* USB_OTG_FS || USB */

#if defined(SDMMC1)
  /* Get the SDMMC1 clock source ---------------------------------------------*/
  PeriphClkInit->Sdmmc1ClockSelection   = __HAL_RCC_GET_SDMMC1_SOURCE();
 8004c64:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c68:	f002 6240 	and.w	r2, r2, #201326592	; 0xc000000
 8004c6c:	6702      	str	r2, [r0, #112]	; 0x70
#endif /* SDMMC1 */

  /* Get the RNG clock source ------------------------------------------------*/
  PeriphClkInit->RngClockSelection   = __HAL_RCC_GET_RNG_SOURCE();
 8004c6e:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c72:	f002 6240 	and.w	r2, r2, #201326592	; 0xc000000
 8004c76:	6742      	str	r2, [r0, #116]	; 0x74

  /* Get the ADC clock source ------------------------------------------------*/
  PeriphClkInit->AdcClockSelection     = __HAL_RCC_GET_ADC_SOURCE();
 8004c78:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c7c:	f002 5240 	and.w	r2, r2, #805306368	; 0x30000000
 8004c80:	6782      	str	r2, [r0, #120]	; 0x78

#if defined(SWPMI1)
  /* Get the SWPMI1 clock source ---------------------------------------------*/
  PeriphClkInit->Swpmi1ClockSelection  = __HAL_RCC_GET_SWPMI1_SOURCE();
 8004c82:	f8d3 2088 	ldr.w	r2, [r3, #136]	; 0x88
 8004c86:	f002 4280 	and.w	r2, r2, #1073741824	; 0x40000000
 8004c8a:	67c2      	str	r2, [r0, #124]	; 0x7c
#endif /* SWPMI1 */

#if defined(DFSDM1_Filter0)
  /* Get the DFSDM1 clock source ---------------------------------------------*/
  PeriphClkInit->Dfsdm1ClockSelection  = __HAL_RCC_GET_DFSDM1_SOURCE();
 8004c8c:	f8d3 3088 	ldr.w	r3, [r3, #136]	; 0x88
 8004c90:	f003 4300 	and.w	r3, r3, #2147483648	; 0x80000000
 8004c94:	f8c0 3080 	str.w	r3, [r0, #128]	; 0x80
 8004c98:	4770      	bx	lr
 8004c9a:	bf00      	nop
 8004c9c:	000fffff 	.word	0x000fffff
 8004ca0:	40021000 	.word	0x40021000

08004ca4 <HAL_RCCEx_GetPeriphCLKFreq>:
  uint32_t pllvco = 0U, plln = 0U, pllp = 0U;

  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));

  if(PeriphClk == RCC_PERIPHCLK_RTC)
 8004ca4:	f5b0 3f00 	cmp.w	r0, #131072	; 0x20000
  @endif
  *            @arg @ref RCC_PERIPHCLK_USB  USB peripheral clock (only for devices with USB)
  * @retval Frequency in Hz
  */
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
{
 8004ca8:	b410      	push	{r4}
 8004caa:	4bc3      	ldr	r3, [pc, #780]	; (8004fb8 <HAL_RCCEx_GetPeriphCLKFreq+0x314>)
  uint32_t pllvco = 0U, plln = 0U, pllp = 0U;

  /* Check the parameters */
  assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));

  if(PeriphClk == RCC_PERIPHCLK_RTC)
 8004cac:	d116      	bne.n	8004cdc <HAL_RCCEx_GetPeriphCLKFreq+0x38>
  {
    /* Get the current RTC source */
    srcclk = __HAL_RCC_GET_RTC_SOURCE();
 8004cae:	f8d3 2090 	ldr.w	r2, [r3, #144]	; 0x90
 8004cb2:	f402 7240 	and.w	r2, r2, #768	; 0x300

    /* Check if LSE is ready and if RTC clock selection is LSE */
    if ((srcclk == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004cb6:	f5b2 7f80 	cmp.w	r2, #256	; 0x100
 8004cba:	f000 81f8 	beq.w	80050ae <HAL_RCCEx_GetPeriphCLKFreq+0x40a>
    {
      frequency = LSE_VALUE;
    }
    /* Check if LSI is ready and if RTC clock selection is LSI */
    else if ((srcclk == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
 8004cbe:	f5b2 7f00 	cmp.w	r2, #512	; 0x200
 8004cc2:	d102      	bne.n	8004cca <HAL_RCCEx_GetPeriphCLKFreq+0x26>
 8004cc4:	f8d3 3094 	ldr.w	r3, [r3, #148]	; 0x94
 8004cc8:	e1e2      	b.n	8005090 <HAL_RCCEx_GetPeriphCLKFreq+0x3ec>
    {
      frequency = LSI_VALUE;
    }
    /* Check if HSE is ready  and if RTC clock selection is HSI_DIV32*/
    else if ((srcclk == RCC_RTCCLKSOURCE_HSE_DIV32) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
 8004cca:	f5b2 7f40 	cmp.w	r2, #768	; 0x300
 8004cce:	f040 81fc 	bne.w	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004cd2:	681b      	ldr	r3, [r3, #0]
    {
      frequency = HSE_VALUE / 32;
 8004cd4:	48b9      	ldr	r0, [pc, #740]	; (8004fbc <HAL_RCCEx_GetPeriphCLKFreq+0x318>)
 8004cd6:	f413 3f00 	tst.w	r3, #131072	; 0x20000
 8004cda:	e1bf      	b.n	800505c <HAL_RCCEx_GetPeriphCLKFreq+0x3b8>
  else
  {
    /* Other external peripheral clock source than RTC */

    /* Compute PLL clock input */
    if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_MSI)        /* MSI ? */
 8004cdc:	68da      	ldr	r2, [r3, #12]
 8004cde:	f002 0203 	and.w	r2, r2, #3
 8004ce2:	2a01      	cmp	r2, #1
 8004ce4:	d111      	bne.n	8004d0a <HAL_RCCEx_GetPeriphCLKFreq+0x66>
    {
      if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
 8004ce6:	681a      	ldr	r2, [r3, #0]
 8004ce8:	f012 0202 	ands.w	r2, r2, #2
 8004cec:	d024      	beq.n	8004d38 <HAL_RCCEx_GetPeriphCLKFreq+0x94>
      {
        /*MSI frequency range in HZ*/
        pllvco = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
 8004cee:	681a      	ldr	r2, [r3, #0]
 8004cf0:	49b3      	ldr	r1, [pc, #716]	; (8004fc0 <HAL_RCCEx_GetPeriphCLKFreq+0x31c>)
 8004cf2:	0712      	lsls	r2, r2, #28
 8004cf4:	bf4b      	itete	mi
 8004cf6:	681a      	ldrmi	r2, [r3, #0]
 8004cf8:	f8d3 2094 	ldrpl.w	r2, [r3, #148]	; 0x94
 8004cfc:	f3c2 1203 	ubfxmi	r2, r2, #4, #4
 8004d00:	f3c2 2203 	ubfxpl	r2, r2, #8, #4
 8004d04:	f851 4022 	ldr.w	r4, [r1, r2, lsl #2]
 8004d08:	e019      	b.n	8004d3e <HAL_RCCEx_GetPeriphCLKFreq+0x9a>
      else
      {
        pllvco = 0U;
      }
    }
    else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI)   /* HSI ? */
 8004d0a:	68da      	ldr	r2, [r3, #12]
 8004d0c:	f002 0203 	and.w	r2, r2, #3
 8004d10:	2a02      	cmp	r2, #2
 8004d12:	d104      	bne.n	8004d1e <HAL_RCCEx_GetPeriphCLKFreq+0x7a>
    {
      if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY))
 8004d14:	681a      	ldr	r2, [r3, #0]
      {
        pllvco = HSI_VALUE;
 8004d16:	f412 6f80 	tst.w	r2, #1024	; 0x400
 8004d1a:	4aaa      	ldr	r2, [pc, #680]	; (8004fc4 <HAL_RCCEx_GetPeriphCLKFreq+0x320>)
 8004d1c:	e008      	b.n	8004d30 <HAL_RCCEx_GetPeriphCLKFreq+0x8c>
      else
      {
        pllvco = 0U;
      }
    }
    else if(__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)   /* HSE ? */
 8004d1e:	68da      	ldr	r2, [r3, #12]
 8004d20:	f002 0203 	and.w	r2, r2, #3
 8004d24:	2a03      	cmp	r2, #3
 8004d26:	d109      	bne.n	8004d3c <HAL_RCCEx_GetPeriphCLKFreq+0x98>
    {
      if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY))
 8004d28:	681a      	ldr	r2, [r3, #0]
      {
        pllvco = HSE_VALUE;
 8004d2a:	f412 3f00 	tst.w	r2, #131072	; 0x20000
 8004d2e:	4aa6      	ldr	r2, [pc, #664]	; (8004fc8 <HAL_RCCEx_GetPeriphCLKFreq+0x324>)
 8004d30:	bf0c      	ite	eq
 8004d32:	2400      	moveq	r4, #0
 8004d34:	4614      	movne	r4, r2
 8004d36:	e002      	b.n	8004d3e <HAL_RCCEx_GetPeriphCLKFreq+0x9a>
      {
        pllvco = HSI_VALUE;
      }
      else
      {
        pllvco = 0U;
 8004d38:	4614      	mov	r4, r2
 8004d3a:	e000      	b.n	8004d3e <HAL_RCCEx_GetPeriphCLKFreq+0x9a>
 8004d3c:	2400      	movs	r4, #0
    {
      pllvco = 0U;
    }

    /* f(PLL Source) / PLLM */
    pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
 8004d3e:	68da      	ldr	r2, [r3, #12]
 8004d40:	499d      	ldr	r1, [pc, #628]	; (8004fb8 <HAL_RCCEx_GetPeriphCLKFreq+0x314>)
 8004d42:	f3c2 1202 	ubfx	r2, r2, #4, #3

    switch(PeriphClk)
 8004d46:	f5b0 7f00 	cmp.w	r0, #512	; 0x200
    {
      pllvco = 0U;
    }

    /* f(PLL Source) / PLLM */
    pllvco = (pllvco / ((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLM) >> RCC_PLLCFGR_PLLM_Pos) + 1U));
 8004d4a:	f102 0201 	add.w	r2, r2, #1
 8004d4e:	fbb4 f2f2 	udiv	r2, r4, r2

    switch(PeriphClk)
 8004d52:	f000 8173 	beq.w	800503c <HAL_RCCEx_GetPeriphCLKFreq+0x398>
 8004d56:	d822      	bhi.n	8004d9e <HAL_RCCEx_GetPeriphCLKFreq+0xfa>
 8004d58:	2810      	cmp	r0, #16
 8004d5a:	f000 80f7 	beq.w	8004f4c <HAL_RCCEx_GetPeriphCLKFreq+0x2a8>
 8004d5e:	d80e      	bhi.n	8004d7e <HAL_RCCEx_GetPeriphCLKFreq+0xda>
 8004d60:	2802      	cmp	r0, #2
 8004d62:	f000 80cb 	beq.w	8004efc <HAL_RCCEx_GetPeriphCLKFreq+0x258>
 8004d66:	d803      	bhi.n	8004d70 <HAL_RCCEx_GetPeriphCLKFreq+0xcc>
 8004d68:	2801      	cmp	r0, #1
 8004d6a:	f000 80b4 	beq.w	8004ed6 <HAL_RCCEx_GetPeriphCLKFreq+0x232>
 8004d6e:	e1ac      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004d70:	2804      	cmp	r0, #4
 8004d72:	f000 80d3 	beq.w	8004f1c <HAL_RCCEx_GetPeriphCLKFreq+0x278>
 8004d76:	2808      	cmp	r0, #8
 8004d78:	f000 80dc 	beq.w	8004f34 <HAL_RCCEx_GetPeriphCLKFreq+0x290>
 8004d7c:	e1a5      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004d7e:	2840      	cmp	r0, #64	; 0x40
 8004d80:	f000 8134 	beq.w	8004fec <HAL_RCCEx_GetPeriphCLKFreq+0x348>
 8004d84:	d803      	bhi.n	8004d8e <HAL_RCCEx_GetPeriphCLKFreq+0xea>
 8004d86:	2820      	cmp	r0, #32
 8004d88:	f000 80ee 	beq.w	8004f68 <HAL_RCCEx_GetPeriphCLKFreq+0x2c4>
 8004d8c:	e19d      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004d8e:	2880      	cmp	r0, #128	; 0x80
 8004d90:	f000 8139 	beq.w	8005006 <HAL_RCCEx_GetPeriphCLKFreq+0x362>
 8004d94:	f5b0 7f80 	cmp.w	r0, #256	; 0x100
 8004d98:	f000 8142 	beq.w	8005020 <HAL_RCCEx_GetPeriphCLKFreq+0x37c>
 8004d9c:	e195      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004d9e:	f5b0 4f80 	cmp.w	r0, #16384	; 0x4000
 8004da2:	f000 80f0 	beq.w	8004f86 <HAL_RCCEx_GetPeriphCLKFreq+0x2e2>
 8004da6:	d80e      	bhi.n	8004dc6 <HAL_RCCEx_GetPeriphCLKFreq+0x122>
 8004da8:	f5b0 6f00 	cmp.w	r0, #2048	; 0x800
 8004dac:	d027      	beq.n	8004dfe <HAL_RCCEx_GetPeriphCLKFreq+0x15a>
 8004dae:	d804      	bhi.n	8004dba <HAL_RCCEx_GetPeriphCLKFreq+0x116>
 8004db0:	f5b0 6f80 	cmp.w	r0, #1024	; 0x400
 8004db4:	f000 8161 	beq.w	800507a <HAL_RCCEx_GetPeriphCLKFreq+0x3d6>
 8004db8:	e187      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004dba:	f5b0 5f80 	cmp.w	r0, #4096	; 0x1000
 8004dbe:	d013      	beq.n	8004de8 <HAL_RCCEx_GetPeriphCLKFreq+0x144>
 8004dc0:	f5b0 5f00 	cmp.w	r0, #8192	; 0x2000
 8004dc4:	e00e      	b.n	8004de4 <HAL_RCCEx_GetPeriphCLKFreq+0x140>
 8004dc6:	f5b0 3f80 	cmp.w	r0, #65536	; 0x10000
 8004dca:	f000 8109 	beq.w	8004fe0 <HAL_RCCEx_GetPeriphCLKFreq+0x33c>
 8004dce:	d804      	bhi.n	8004dda <HAL_RCCEx_GetPeriphCLKFreq+0x136>
 8004dd0:	f5b0 4f00 	cmp.w	r0, #32768	; 0x8000
 8004dd4:	f000 816e 	beq.w	80050b4 <HAL_RCCEx_GetPeriphCLKFreq+0x410>
 8004dd8:	e177      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8004dda:	f5b0 2f80 	cmp.w	r0, #262144	; 0x40000
 8004dde:	d039      	beq.n	8004e54 <HAL_RCCEx_GetPeriphCLKFreq+0x1b0>
 8004de0:	f5b0 2f00 	cmp.w	r0, #524288	; 0x80000
 8004de4:	d036      	beq.n	8004e54 <HAL_RCCEx_GetPeriphCLKFreq+0x1b0>
 8004de6:	e170      	b.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
        }
        /* Else, PLL clock output to check below */
      }
      else /* RCC_PERIPHCLK_SAI2 */
      {
        srcclk = __HAL_RCC_GET_SAI2_SOURCE();
 8004de8:	f8d1 0088 	ldr.w	r0, [r1, #136]	; 0x88
 8004dec:	f000 7040 	and.w	r0, r0, #50331648	; 0x3000000

        if(srcclk == RCC_SAI2CLKSOURCE_PIN)
 8004df0:	f1b0 7f40 	cmp.w	r0, #50331648	; 0x3000000
 8004df4:	f000 8166 	beq.w	80050c4 <HAL_RCCEx_GetPeriphCLKFreq+0x420>
#endif /* SAI2 */

      if(frequency == 0U)
      {
#if defined(SAI2)
        if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL))
 8004df8:	f1b0 7f00 	cmp.w	r0, #33554432	; 0x2000000
 8004dfc:	e009      	b.n	8004e12 <HAL_RCCEx_GetPeriphCLKFreq+0x16e>
    case RCC_PERIPHCLK_SAI1:
    case RCC_PERIPHCLK_SAI2:

      if(PeriphClk == RCC_PERIPHCLK_SAI1)
      {
        srcclk = __HAL_RCC_GET_SAI1_SOURCE();
 8004dfe:	f8d3 0088 	ldr.w	r0, [r3, #136]	; 0x88
 8004e02:	f400 0040 	and.w	r0, r0, #12582912	; 0xc00000

        if(srcclk == RCC_SAI1CLKSOURCE_PIN)
 8004e06:	f5b0 0f40 	cmp.w	r0, #12582912	; 0xc00000
 8004e0a:	f000 815b 	beq.w	80050c4 <HAL_RCCEx_GetPeriphCLKFreq+0x420>
#endif /* SAI2 */

      if(frequency == 0U)
      {
#if defined(SAI2)
        if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL))
 8004e0e:	f5b0 0f00 	cmp.w	r0, #8388608	; 0x800000
 8004e12:	d10a      	bne.n	8004e2a <HAL_RCCEx_GetPeriphCLKFreq+0x186>
        {
          if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET)
 8004e14:	68db      	ldr	r3, [r3, #12]
 8004e16:	4968      	ldr	r1, [pc, #416]	; (8004fb8 <HAL_RCCEx_GetPeriphCLKFreq+0x314>)
 8004e18:	f413 3080 	ands.w	r0, r3, #65536	; 0x10000
 8004e1c:	f000 8156 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
          {
            /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */
            plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
 8004e20:	68c8      	ldr	r0, [r1, #12]
#if defined(RCC_PLLP_DIV_2_31_SUPPORT)
            pllp = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLPDIV) >> RCC_PLLCFGR_PLLPDIV_Pos;
#endif
            if(pllp == 0U)
            {
              if(READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLP) != RESET)
 8004e22:	68cb      	ldr	r3, [r1, #12]
        if((srcclk == RCC_SAI1CLKSOURCE_PLL) || (srcclk == RCC_SAI2CLKSOURCE_PLL))
        {
          if(__HAL_RCC_GET_PLLCLKOUT_CONFIG(RCC_PLL_SAI3CLK) != RESET)
          {
            /* f(PLLSAI3CLK) = f(VCO input) * PLLN / PLLP */
            plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
 8004e24:	f3c0 2006 	ubfx	r0, r0, #8, #7
 8004e28:	e00b      	b.n	8004e42 <HAL_RCCEx_GetPeriphCLKFreq+0x19e>
              }
            }
            frequency = (pllvco * plln) / pllp;
          }
        }
        else if(srcclk == 0U)  /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */
 8004e2a:	2800      	cmp	r0, #0
 8004e2c:	f040 814d 	bne.w	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
        {
          if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET)
 8004e30:	691b      	ldr	r3, [r3, #16]
 8004e32:	4961      	ldr	r1, [pc, #388]	; (8004fb8 <HAL_RCCEx_GetPeriphCLKFreq+0x314>)
 8004e34:	03dc      	lsls	r4, r3, #15
 8004e36:	f140 8149 	bpl.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
          {
            /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */
            plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
 8004e3a:	6908      	ldr	r0, [r1, #16]
#if defined(RCC_PLLSAI1P_DIV_2_31_SUPPORT)
            pllp = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1PDIV) >> RCC_PLLSAI1CFGR_PLLSAI1PDIV_Pos;
#endif
            if(pllp == 0U)
            {
              if(READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1P) != RESET)
 8004e3c:	690b      	ldr	r3, [r1, #16]
        else if(srcclk == 0U)  /* RCC_SAI1CLKSOURCE_PLLSAI1 || RCC_SAI2CLKSOURCE_PLLSAI1 */
        {
          if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_SAI1CLK) != RESET)
          {
            /* f(PLLSAI1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1P */
            plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
 8004e3e:	f3c0 2006 	ubfx	r0, r0, #8, #7
              {
                pllp = 17U;
              }
              else
              {
                pllp = 7U;
 8004e42:	f413 3f00 	tst.w	r3, #131072	; 0x20000
 8004e46:	bf14      	ite	ne
 8004e48:	2311      	movne	r3, #17
 8004e4a:	2307      	moveq	r3, #7
              }
            }
            frequency = (pllvco * plln) / pllp;
 8004e4c:	4350      	muls	r0, r2
 8004e4e:	fbb0 f0f3 	udiv	r0, r0, r3
 8004e52:	e13b      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>

    case RCC_PERIPHCLK_SDMMC1:

#endif /* SDMMC1 */

      srcclk = READ_BIT(RCC->CCIPR, RCC_CCIPR_CLK48SEL);
 8004e54:	f8d3 3088 	ldr.w	r3, [r3, #136]	; 0x88
 8004e58:	4957      	ldr	r1, [pc, #348]	; (8004fb8 <HAL_RCCEx_GetPeriphCLKFreq+0x314>)
 8004e5a:	f003 6340 	and.w	r3, r3, #201326592	; 0xc000000

      if(srcclk == RCC_CCIPR_CLK48SEL)   /* MSI ? */
 8004e5e:	f1b3 6f40 	cmp.w	r3, #201326592	; 0xc000000
 8004e62:	d112      	bne.n	8004e8a <HAL_RCCEx_GetPeriphCLKFreq+0x1e6>
      {
        if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_MSIRDY))
 8004e64:	6808      	ldr	r0, [r1, #0]
 8004e66:	f010 0002 	ands.w	r0, r0, #2
 8004e6a:	f000 812f 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        {
          /*MSI frequency range in HZ*/
          frequency = MSIRangeTable[(__HAL_RCC_GET_MSI_RANGE() >> 4U)];
 8004e6e:	680b      	ldr	r3, [r1, #0]
 8004e70:	4a53      	ldr	r2, [pc, #332]	; (8004fc0 <HAL_RCCEx_GetPeriphCLKFreq+0x31c>)
 8004e72:	071b      	lsls	r3, r3, #28
 8004e74:	bf4b      	itete	mi
 8004e76:	680b      	ldrmi	r3, [r1, #0]
 8004e78:	f8d1 3094 	ldrpl.w	r3, [r1, #148]	; 0x94
 8004e7c:	f3c3 1303 	ubfxmi	r3, r3, #4, #4
 8004e80:	f3c3 2303 	ubfxpl	r3, r3, #8, #4
 8004e84:	f852 0023 	ldr.w	r0, [r2, r3, lsl #2]
 8004e88:	e120      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        else
        {
          frequency = 0U;
        }
      }
      else if(srcclk == RCC_CCIPR_CLK48SEL_1)  /* PLL ? */
 8004e8a:	f1b3 6f00 	cmp.w	r3, #134217728	; 0x8000000
 8004e8e:	d10c      	bne.n	8004eaa <HAL_RCCEx_GetPeriphCLKFreq+0x206>
      {
        if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLRDY) && HAL_IS_BIT_SET(RCC->PLLCFGR, RCC_PLLCFGR_PLLQEN))
 8004e90:	680b      	ldr	r3, [r1, #0]
 8004e92:	f013 7000 	ands.w	r0, r3, #33554432	; 0x2000000
 8004e96:	f000 8119 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
 8004e9a:	68cb      	ldr	r3, [r1, #12]
 8004e9c:	f413 1080 	ands.w	r0, r3, #1048576	; 0x100000
 8004ea0:	f000 8114 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        {
          /* f(PLL48M1CLK) = f(VCO input) * PLLN / PLLQ */
          plln = READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos;
 8004ea4:	68c8      	ldr	r0, [r1, #12]
          frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLCFGR, RCC_PLLCFGR_PLLQ) >> RCC_PLLCFGR_PLLQ_Pos) + 1U) << 1U);
 8004ea6:	68cb      	ldr	r3, [r1, #12]
 8004ea8:	e00f      	b.n	8004eca <HAL_RCCEx_GetPeriphCLKFreq+0x226>
        else
        {
          frequency = 0U;
        }
      }
      else if(srcclk == RCC_CCIPR_CLK48SEL_0)  /* PLLSAI1 ? */
 8004eaa:	f1b3 6f80 	cmp.w	r3, #67108864	; 0x4000000
 8004eae:	f040 810c 	bne.w	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
      {
        if(HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLSAI1RDY) && HAL_IS_BIT_SET(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1QEN))
 8004eb2:	680b      	ldr	r3, [r1, #0]
 8004eb4:	f013 6000 	ands.w	r0, r3, #134217728	; 0x8000000
 8004eb8:	f000 8108 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
 8004ebc:	690b      	ldr	r3, [r1, #16]
 8004ebe:	f413 1080 	ands.w	r0, r3, #1048576	; 0x100000
 8004ec2:	f000 8103 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        {
          /* f(PLL48M2CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1Q */
          plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
 8004ec6:	6908      	ldr	r0, [r1, #16]
          frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1Q) >> RCC_PLLSAI1CFGR_PLLSAI1Q_Pos) + 1U) << 1U);
 8004ec8:	690b      	ldr	r3, [r1, #16]
 8004eca:	f3c0 2006 	ubfx	r0, r0, #8, #7
 8004ece:	4350      	muls	r0, r2
 8004ed0:	f3c3 5341 	ubfx	r3, r3, #21, #2
 8004ed4:	e06d      	b.n	8004fb2 <HAL_RCCEx_GetPeriphCLKFreq+0x30e>
#endif /* RCC_HSI48_SUPPORT */
      break;

    case RCC_PERIPHCLK_USART1:
      /* Get the current USART1 source */
      srcclk = __HAL_RCC_GET_USART1_SOURCE();
 8004ed6:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_USART1CLKSOURCE_PCLK2)
 8004eda:	f012 0203 	ands.w	r2, r2, #3
 8004ede:	d103      	bne.n	8004ee8 <HAL_RCCEx_GetPeriphCLKFreq+0x244>
      break;
    }
  }

  return(frequency);
}
 8004ee0:	f85d 4b04 	ldr.w	r4, [sp], #4
      /* Get the current USART1 source */
      srcclk = __HAL_RCC_GET_USART1_SOURCE();

      if(srcclk == RCC_USART1CLKSOURCE_PCLK2)
      {
        frequency = HAL_RCC_GetPCLK2Freq();
 8004ee4:	f7ff bb40 	b.w	8004568 <HAL_RCC_GetPCLK2Freq>
      }
      else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK)
 8004ee8:	2a01      	cmp	r2, #1
 8004eea:	d103      	bne.n	8004ef4 <HAL_RCCEx_GetPeriphCLKFreq+0x250>
      break;
    }
  }

  return(frequency);
}
 8004eec:	f85d 4b04 	ldr.w	r4, [sp], #4
      {
        frequency = HAL_RCC_GetPCLK2Freq();
      }
      else if(srcclk == RCC_USART1CLKSOURCE_SYSCLK)
      {
        frequency = HAL_RCC_GetSysClockFreq();
 8004ef0:	f7fe bff6 	b.w	8003ee0 <HAL_RCC_GetSysClockFreq>
      }
      else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004ef4:	2a02      	cmp	r2, #2
 8004ef6:	f040 80da 	bne.w	80050ae <HAL_RCCEx_GetPeriphCLKFreq+0x40a>
 8004efa:	e0d3      	b.n	80050a4 <HAL_RCCEx_GetPeriphCLKFreq+0x400>
      }
      break;

    case RCC_PERIPHCLK_USART2:
      /* Get the current USART2 source */
      srcclk = __HAL_RCC_GET_USART2_SOURCE();
 8004efc:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_USART2CLKSOURCE_PCLK1)
 8004f00:	f013 030c 	ands.w	r3, r3, #12
 8004f04:	d103      	bne.n	8004f0e <HAL_RCCEx_GetPeriphCLKFreq+0x26a>
      break;
    }
  }

  return(frequency);
}
 8004f06:	f85d 4b04 	ldr.w	r4, [sp], #4
      /* Get the current USART2 source */
      srcclk = __HAL_RCC_GET_USART2_SOURCE();

      if(srcclk == RCC_USART2CLKSOURCE_PCLK1)
      {
        frequency = HAL_RCC_GetPCLK1Freq();
 8004f0a:	f7ff bb1d 	b.w	8004548 <HAL_RCC_GetPCLK1Freq>
      }
      else if(srcclk == RCC_USART2CLKSOURCE_SYSCLK)
 8004f0e:	2b04      	cmp	r3, #4
 8004f10:	d0ec      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_USART2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004f12:	2b08      	cmp	r3, #8
 8004f14:	f000 809e 	beq.w	8005054 <HAL_RCCEx_GetPeriphCLKFreq+0x3b0>
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_USART2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004f18:	2b0c      	cmp	r3, #12
 8004f1a:	e0a4      	b.n	8005066 <HAL_RCCEx_GetPeriphCLKFreq+0x3c2>

#if defined(USART3)

    case RCC_PERIPHCLK_USART3:
      /* Get the current USART3 source */
      srcclk = __HAL_RCC_GET_USART3_SOURCE();
 8004f1c:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_USART3CLKSOURCE_PCLK1)
 8004f20:	f012 0230 	ands.w	r2, r2, #48	; 0x30
 8004f24:	d0ef      	beq.n	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_USART3CLKSOURCE_SYSCLK)
 8004f26:	2a10      	cmp	r2, #16
 8004f28:	d0e0      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_USART3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004f2a:	2a20      	cmp	r2, #32
 8004f2c:	f000 80ba 	beq.w	80050a4 <HAL_RCCEx_GetPeriphCLKFreq+0x400>
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_USART3CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004f30:	2a30      	cmp	r2, #48	; 0x30
 8004f32:	e0bb      	b.n	80050ac <HAL_RCCEx_GetPeriphCLKFreq+0x408>

#if defined(UART4)

    case RCC_PERIPHCLK_UART4:
      /* Get the current UART4 source */
      srcclk = __HAL_RCC_GET_UART4_SOURCE();
 8004f34:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_UART4CLKSOURCE_PCLK1)
 8004f38:	f012 02c0 	ands.w	r2, r2, #192	; 0xc0
 8004f3c:	d0e3      	beq.n	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_UART4CLKSOURCE_SYSCLK)
 8004f3e:	2a40      	cmp	r2, #64	; 0x40
 8004f40:	d0d4      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_UART4CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004f42:	2a80      	cmp	r2, #128	; 0x80
 8004f44:	f000 80ae 	beq.w	80050a4 <HAL_RCCEx_GetPeriphCLKFreq+0x400>
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_UART4CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004f48:	2ac0      	cmp	r2, #192	; 0xc0
 8004f4a:	e0af      	b.n	80050ac <HAL_RCCEx_GetPeriphCLKFreq+0x408>

#if defined(UART5)

    case RCC_PERIPHCLK_UART5:
      /* Get the current UART5 source */
      srcclk = __HAL_RCC_GET_UART5_SOURCE();
 8004f4c:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_UART5CLKSOURCE_PCLK1)
 8004f50:	f413 7340 	ands.w	r3, r3, #768	; 0x300
 8004f54:	d0d7      	beq.n	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_UART5CLKSOURCE_SYSCLK)
 8004f56:	f5b3 7f80 	cmp.w	r3, #256	; 0x100
 8004f5a:	d0c7      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_UART5CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004f5c:	f5b3 7f00 	cmp.w	r3, #512	; 0x200
 8004f60:	d078      	beq.n	8005054 <HAL_RCCEx_GetPeriphCLKFreq+0x3b0>
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_UART5CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004f62:	f5b3 7f40 	cmp.w	r3, #768	; 0x300
 8004f66:	e07e      	b.n	8005066 <HAL_RCCEx_GetPeriphCLKFreq+0x3c2>

#endif /* UART5 */

    case RCC_PERIPHCLK_LPUART1:
      /* Get the current LPUART1 source */
      srcclk = __HAL_RCC_GET_LPUART1_SOURCE();
 8004f68:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_LPUART1CLKSOURCE_PCLK1)
 8004f6c:	f412 6240 	ands.w	r2, r2, #3072	; 0xc00
 8004f70:	d0c9      	beq.n	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_LPUART1CLKSOURCE_SYSCLK)
 8004f72:	f5b2 6f80 	cmp.w	r2, #1024	; 0x400
 8004f76:	d0b9      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_LPUART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004f78:	f5b2 6f00 	cmp.w	r2, #2048	; 0x800
 8004f7c:	f000 8092 	beq.w	80050a4 <HAL_RCCEx_GetPeriphCLKFreq+0x400>
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_LPUART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8004f80:	f5b2 6f40 	cmp.w	r2, #3072	; 0xc00
 8004f84:	e092      	b.n	80050ac <HAL_RCCEx_GetPeriphCLKFreq+0x408>
      }
      break;

    case RCC_PERIPHCLK_ADC:

      srcclk = __HAL_RCC_GET_ADC_SOURCE();
 8004f86:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88
 8004f8a:	f003 5340 	and.w	r3, r3, #805306368	; 0x30000000

      if(srcclk == RCC_ADCCLKSOURCE_SYSCLK)
 8004f8e:	f1b3 5f40 	cmp.w	r3, #805306368	; 0x30000000
 8004f92:	d0ab      	beq.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI1)
 8004f94:	f1b3 5f80 	cmp.w	r3, #268435456	; 0x10000000
 8004f98:	d118      	bne.n	8004fcc <HAL_RCCEx_GetPeriphCLKFreq+0x328>
      {
        if(__HAL_RCC_GET_PLLSAI1CLKOUT_CONFIG(RCC_PLLSAI1_ADC1CLK) != RESET)
 8004f9a:	690b      	ldr	r3, [r1, #16]
 8004f9c:	f013 7080 	ands.w	r0, r3, #16777216	; 0x1000000
 8004fa0:	f000 8094 	beq.w	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        {
          /* f(PLLADC1CLK) = f(VCOSAI1 input) * PLLSAI1N / PLLSAI1R */
          plln = READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1N) >> RCC_PLLSAI1CFGR_PLLSAI1N_Pos;
 8004fa4:	6908      	ldr	r0, [r1, #16]
          frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI1CFGR, RCC_PLLSAI1CFGR_PLLSAI1R) >> RCC_PLLSAI1CFGR_PLLSAI1R_Pos) + 1U) << 1U);
 8004fa6:	690b      	ldr	r3, [r1, #16]
 8004fa8:	f3c0 2006 	ubfx	r0, r0, #8, #7
 8004fac:	4350      	muls	r0, r2
 8004fae:	f3c3 6341 	ubfx	r3, r3, #25, #2
 8004fb2:	3301      	adds	r3, #1
 8004fb4:	005b      	lsls	r3, r3, #1
 8004fb6:	e74a      	b.n	8004e4e <HAL_RCCEx_GetPeriphCLKFreq+0x1aa>
 8004fb8:	40021000 	.word	0x40021000
 8004fbc:	0003d090 	.word	0x0003d090
 8004fc0:	08006988 	.word	0x08006988
 8004fc4:	00f42400 	.word	0x00f42400
 8004fc8:	007a1200 	.word	0x007a1200
        }
      }
#if defined(STM32L471xx) || defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L485xx) || defined(STM32L486xx) || defined(STM32L496xx) || defined(STM32L4A6xx)
      else if(srcclk == RCC_ADCCLKSOURCE_PLLSAI2)
 8004fcc:	f1b3 5f00 	cmp.w	r3, #536870912	; 0x20000000
 8004fd0:	d17b      	bne.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
      {
        if(__HAL_RCC_GET_PLLSAI2CLKOUT_CONFIG(RCC_PLLSAI2_ADC2CLK) != RESET)
 8004fd2:	694b      	ldr	r3, [r1, #20]
 8004fd4:	f013 7080 	ands.w	r0, r3, #16777216	; 0x1000000
 8004fd8:	d078      	beq.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
        {
          /* f(PLLADC2CLK) = f(VCOSAI2 input) * PLLSAI2N / PLLSAI2R */
          plln = READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2N) >> RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
 8004fda:	6948      	ldr	r0, [r1, #20]
          frequency = (pllvco * plln) / (((READ_BIT(RCC->PLLSAI2CFGR, RCC_PLLSAI2CFGR_PLLSAI2R) >> RCC_PLLSAI2CFGR_PLLSAI2R_Pos) + 1U) << 1U);
 8004fdc:	694b      	ldr	r3, [r1, #20]
 8004fde:	e7e3      	b.n	8004fa8 <HAL_RCCEx_GetPeriphCLKFreq+0x304>

#if defined(DFSDM1_Filter0)

    case RCC_PERIPHCLK_DFSDM1:
      /* Get the current DFSDM1 source */
      srcclk = __HAL_RCC_GET_DFSDM1_SOURCE();
 8004fe0:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_DFSDM1CLKSOURCE_PCLK2)
 8004fe4:	2b00      	cmp	r3, #0
 8004fe6:	f6bf af7b 	bge.w	8004ee0 <HAL_RCCEx_GetPeriphCLKFreq+0x23c>
 8004fea:	e77f      	b.n	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>

#endif /* DFSDM1_Filter0 */

    case RCC_PERIPHCLK_I2C1:
      /* Get the current I2C1 source */
      srcclk = __HAL_RCC_GET_I2C1_SOURCE();
 8004fec:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_I2C1CLKSOURCE_PCLK1)
 8004ff0:	f413 5340 	ands.w	r3, r3, #12288	; 0x3000
 8004ff4:	d087      	beq.n	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_I2C1CLKSOURCE_SYSCLK)
 8004ff6:	f5b3 5f80 	cmp.w	r3, #4096	; 0x1000
 8004ffa:	f43f af77 	beq.w	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_I2C1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8004ffe:	f5b3 5f00 	cmp.w	r3, #8192	; 0x2000
 8005002:	d162      	bne.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8005004:	e026      	b.n	8005054 <HAL_RCCEx_GetPeriphCLKFreq+0x3b0>

#if defined(I2C2)

    case RCC_PERIPHCLK_I2C2:
      /* Get the current I2C2 source */
      srcclk = __HAL_RCC_GET_I2C2_SOURCE();
 8005006:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_I2C2CLKSOURCE_PCLK1)
 800500a:	f412 4240 	ands.w	r2, r2, #49152	; 0xc000
 800500e:	f43f af7a 	beq.w	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_I2C2CLKSOURCE_SYSCLK)
 8005012:	f5b2 4f80 	cmp.w	r2, #16384	; 0x4000
 8005016:	f43f af69 	beq.w	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_I2C2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 800501a:	f5b2 4f00 	cmp.w	r2, #32768	; 0x8000
 800501e:	e00b      	b.n	8005038 <HAL_RCCEx_GetPeriphCLKFreq+0x394>

#endif /* I2C2 */

    case RCC_PERIPHCLK_I2C3:
      /* Get the current I2C3 source */
      srcclk = __HAL_RCC_GET_I2C3_SOURCE();
 8005020:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_I2C3CLKSOURCE_PCLK1)
 8005024:	f412 3240 	ands.w	r2, r2, #196608	; 0x30000
 8005028:	f43f af6d 	beq.w	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if(srcclk == RCC_I2C3CLKSOURCE_SYSCLK)
 800502c:	f5b2 3f80 	cmp.w	r2, #65536	; 0x10000
 8005030:	f43f af5c 	beq.w	8004eec <HAL_RCCEx_GetPeriphCLKFreq+0x248>
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_I2C3CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 8005034:	f5b2 3f00 	cmp.w	r2, #131072	; 0x20000
 8005038:	d147      	bne.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 800503a:	e033      	b.n	80050a4 <HAL_RCCEx_GetPeriphCLKFreq+0x400>

#endif /* I2C4 */

    case RCC_PERIPHCLK_LPTIM1:
      /* Get the current LPTIM1 source */
      srcclk = __HAL_RCC_GET_LPTIM1_SOURCE();
 800503c:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_LPTIM1CLKSOURCE_PCLK1)
 8005040:	f413 2340 	ands.w	r3, r3, #786432	; 0xc0000
 8005044:	f43f af5f 	beq.w	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
 8005048:	f5b3 2f80 	cmp.w	r3, #262144	; 0x40000
 800504c:	d01e      	beq.n	800508c <HAL_RCCEx_GetPeriphCLKFreq+0x3e8>
      {
        frequency = LSI_VALUE;
      }
      else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 800504e:	f5b3 2f00 	cmp.w	r3, #524288	; 0x80000
 8005052:	d106      	bne.n	8005062 <HAL_RCCEx_GetPeriphCLKFreq+0x3be>
 8005054:	680b      	ldr	r3, [r1, #0]
      {
        frequency = HAL_RCC_GetSysClockFreq();
      }
      else if((srcclk == RCC_USART1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
      {
        frequency = HSI_VALUE;
 8005056:	481f      	ldr	r0, [pc, #124]	; (80050d4 <HAL_RCCEx_GetPeriphCLKFreq+0x430>)
 8005058:	f413 6f80 	tst.w	r3, #1024	; 0x400
 800505c:	bf08      	it	eq
 800505e:	2000      	moveq	r0, #0
 8005060:	e034      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
      }
      else if((srcclk == RCC_LPTIM1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
      {
        frequency = HSI_VALUE;
      }
      else if ((srcclk == RCC_LPTIM1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 8005062:	f5b3 2f40 	cmp.w	r3, #786432	; 0xc0000
 8005066:	d130      	bne.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 8005068:	f8d1 3090 	ldr.w	r3, [r1, #144]	; 0x90
      {
        frequency = HSI_VALUE;
      }
      else if((srcclk == RCC_USART1CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
      {
        frequency = LSE_VALUE;
 800506c:	f013 0f02 	tst.w	r3, #2
 8005070:	bf0c      	ite	eq
 8005072:	2000      	moveq	r0, #0
 8005074:	f44f 4000 	movne.w	r0, #32768	; 0x8000
 8005078:	e028      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
      }
      break;

    case RCC_PERIPHCLK_LPTIM2:
      /* Get the current LPTIM2 source */
      srcclk = __HAL_RCC_GET_LPTIM2_SOURCE();
 800507a:	f8d1 2088 	ldr.w	r2, [r1, #136]	; 0x88

      if(srcclk == RCC_LPTIM2CLKSOURCE_PCLK1)
 800507e:	f412 1240 	ands.w	r2, r2, #3145728	; 0x300000
 8005082:	f43f af40 	beq.w	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
 8005086:	f5b2 1f80 	cmp.w	r2, #1048576	; 0x100000
 800508a:	d108      	bne.n	800509e <HAL_RCCEx_GetPeriphCLKFreq+0x3fa>
 800508c:	f8d1 3094 	ldr.w	r3, [r1, #148]	; 0x94
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if((srcclk == RCC_LPTIM1CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
      {
        frequency = LSI_VALUE;
 8005090:	f013 0f02 	tst.w	r3, #2
 8005094:	bf0c      	ite	eq
 8005096:	2000      	moveq	r0, #0
 8005098:	f44f 40fa 	movne.w	r0, #32000	; 0x7d00
 800509c:	e016      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
      }
      else if((srcclk == RCC_LPTIM2CLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
      {
        frequency = LSI_VALUE;
      }
      else if((srcclk == RCC_LPTIM2CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 800509e:	f5b2 1f00 	cmp.w	r2, #2097152	; 0x200000
 80050a2:	d101      	bne.n	80050a8 <HAL_RCCEx_GetPeriphCLKFreq+0x404>
 80050a4:	681b      	ldr	r3, [r3, #0]
 80050a6:	e7d6      	b.n	8005056 <HAL_RCCEx_GetPeriphCLKFreq+0x3b2>
      {
        frequency = HSI_VALUE;
      }
      else if ((srcclk == RCC_LPTIM2CLKSOURCE_LSE) && (HAL_IS_BIT_SET(RCC->BDCR, RCC_BDCR_LSERDY)))
 80050a8:	f5b2 1f40 	cmp.w	r2, #3145728	; 0x300000
 80050ac:	d10d      	bne.n	80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 80050ae:	f8d3 3090 	ldr.w	r3, [r3, #144]	; 0x90
 80050b2:	e7db      	b.n	800506c <HAL_RCCEx_GetPeriphCLKFreq+0x3c8>

#if defined(SWPMI1)

    case RCC_PERIPHCLK_SWPMI1:
      /* Get the current SWPMI1 source */
      srcclk = __HAL_RCC_GET_SWPMI1_SOURCE();
 80050b4:	f8d1 3088 	ldr.w	r3, [r1, #136]	; 0x88

      if(srcclk == RCC_SWPMI1CLKSOURCE_PCLK1)
 80050b8:	f013 4380 	ands.w	r3, r3, #1073741824	; 0x40000000
 80050bc:	f43f af23 	beq.w	8004f06 <HAL_RCCEx_GetPeriphCLKFreq+0x262>
      {
        frequency = HAL_RCC_GetPCLK1Freq();
      }
      else if((srcclk == RCC_SWPMI1CLKSOURCE_HSI) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSIRDY)))
 80050c0:	b11b      	cbz	r3, 80050ca <HAL_RCCEx_GetPeriphCLKFreq+0x426>
 80050c2:	e7c7      	b.n	8005054 <HAL_RCCEx_GetPeriphCLKFreq+0x3b0>
 80050c4:	f64b 3080 	movw	r0, #48000	; 0xbb80
 80050c8:	e000      	b.n	80050cc <HAL_RCCEx_GetPeriphCLKFreq+0x428>
      frequency = HSE_VALUE / 32;
    }
    /* Clock not enabled for RTC*/
    else
    {
      frequency = 0U;
 80050ca:	2000      	movs	r0, #0
      break;
    }
  }

  return(frequency);
}
 80050cc:	f85d 4b04 	ldr.w	r4, [sp], #4
 80050d0:	4770      	bx	lr
 80050d2:	bf00      	nop
 80050d4:	00f42400 	.word	0x00f42400

080050d8 <HAL_RCCEx_EnablePLLSAI1>:
  * @param  PLLSAI1Init  pointer to an RCC_PLLSAI1InitTypeDef structure that
  *         contains the configuration information for the PLLSAI1
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef  *PLLSAI1Init)
{
 80050d8:	b570      	push	{r4, r5, r6, lr}
  assert_param(IS_RCC_PLLSAI1Q_VALUE(PLLSAI1Init->PLLSAI1Q));
  assert_param(IS_RCC_PLLSAI1R_VALUE(PLLSAI1Init->PLLSAI1R));
  assert_param(IS_RCC_PLLSAI1CLOCKOUT_VALUE(PLLSAI1Init->PLLSAI1ClockOut));

  /* Disable the PLLSAI1 */
  __HAL_RCC_PLLSAI1_DISABLE();
 80050da:	4c1d      	ldr	r4, [pc, #116]	; (8005150 <HAL_RCCEx_EnablePLLSAI1+0x78>)
 80050dc:	6823      	ldr	r3, [r4, #0]
 80050de:	f023 6380 	bic.w	r3, r3, #67108864	; 0x4000000
 80050e2:	6023      	str	r3, [r4, #0]
  * @param  PLLSAI1Init  pointer to an RCC_PLLSAI1InitTypeDef structure that
  *         contains the configuration information for the PLLSAI1
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_EnablePLLSAI1(RCC_PLLSAI1InitTypeDef  *PLLSAI1Init)
{
 80050e4:	4605      	mov	r5, r0

  /* Disable the PLLSAI1 */
  __HAL_RCC_PLLSAI1_DISABLE();

  /* Get Start Tick*/
  tickstart = HAL_GetTick();
 80050e6:	f7fb fca7 	bl	8000a38 <HAL_GetTick>
 80050ea:	4606      	mov	r6, r0

  /* Wait till PLLSAI1 is ready to be updated */
  while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
 80050ec:	6823      	ldr	r3, [r4, #0]
 80050ee:	4818      	ldr	r0, [pc, #96]	; (8005150 <HAL_RCCEx_EnablePLLSAI1+0x78>)
 80050f0:	011a      	lsls	r2, r3, #4
 80050f2:	d506      	bpl.n	8005102 <HAL_RCCEx_EnablePLLSAI1+0x2a>
  {
    if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
 80050f4:	f7fb fca0 	bl	8000a38 <HAL_GetTick>
 80050f8:	1b80      	subs	r0, r0, r6
 80050fa:	2802      	cmp	r0, #2
 80050fc:	d9f6      	bls.n	80050ec <HAL_RCCEx_EnablePLLSAI1+0x14>
    {
      status = HAL_TIMEOUT;
 80050fe:	2003      	movs	r0, #3
 8005100:	bd70      	pop	{r4, r5, r6, pc}

  if(status == HAL_OK)
  {
    /* Configure the PLLSAI1 Multiplication factor N */
    /* Configure the PLLSAI1 Division factors P, Q and R */
    __HAL_RCC_PLLSAI1_CONFIG(PLLSAI1Init->PLLSAI1N, PLLSAI1Init->PLLSAI1P, PLLSAI1Init->PLLSAI1Q, PLLSAI1Init->PLLSAI1R);
 8005102:	68ea      	ldr	r2, [r5, #12]
 8005104:	68ab      	ldr	r3, [r5, #8]
 8005106:	0912      	lsrs	r2, r2, #4
 8005108:	021b      	lsls	r3, r3, #8
 800510a:	ea43 4142 	orr.w	r1, r3, r2, lsl #17
 800510e:	692b      	ldr	r3, [r5, #16]
 8005110:	085b      	lsrs	r3, r3, #1
 8005112:	3b01      	subs	r3, #1
 8005114:	ea41 5243 	orr.w	r2, r1, r3, lsl #21
 8005118:	696b      	ldr	r3, [r5, #20]
 800511a:	085b      	lsrs	r3, r3, #1
 800511c:	3b01      	subs	r3, #1
 800511e:	ea42 6343 	orr.w	r3, r2, r3, lsl #25
 8005122:	6103      	str	r3, [r0, #16]
    /* Configure the PLLSAI1 Clock output(s) */
    __HAL_RCC_PLLSAI1CLKOUT_ENABLE(PLLSAI1Init->PLLSAI1ClockOut);
 8005124:	6902      	ldr	r2, [r0, #16]
 8005126:	69ab      	ldr	r3, [r5, #24]
 8005128:	4313      	orrs	r3, r2
 800512a:	6103      	str	r3, [r0, #16]

    /* Enable the PLLSAI1 again by setting PLLSAI1ON to 1*/
    __HAL_RCC_PLLSAI1_ENABLE();
 800512c:	6803      	ldr	r3, [r0, #0]
 800512e:	f043 6380 	orr.w	r3, r3, #67108864	; 0x4000000
 8005132:	6003      	str	r3, [r0, #0]

    /* Get Start Tick*/
    tickstart = HAL_GetTick();
 8005134:	f7fb fc80 	bl	8000a38 <HAL_GetTick>
 8005138:	4605      	mov	r5, r0

    /* Wait till PLLSAI1 is ready */
    while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) == RESET)
 800513a:	6823      	ldr	r3, [r4, #0]
 800513c:	011b      	lsls	r3, r3, #4
 800513e:	d405      	bmi.n	800514c <HAL_RCCEx_EnablePLLSAI1+0x74>
    {
      if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
 8005140:	f7fb fc7a 	bl	8000a38 <HAL_GetTick>
 8005144:	1b40      	subs	r0, r0, r5
 8005146:	2802      	cmp	r0, #2
 8005148:	d9f7      	bls.n	800513a <HAL_RCCEx_EnablePLLSAI1+0x62>
 800514a:	e7d8      	b.n	80050fe <HAL_RCCEx_EnablePLLSAI1+0x26>
 800514c:	2000      	movs	r0, #0
        break;
      }
    }
  }

  return status;
 800514e:	bd70      	pop	{r4, r5, r6, pc}
 8005150:	40021000 	.word	0x40021000

08005154 <HAL_RCCEx_DisablePLLSAI1>:
/**
  * @brief  Disable PLLSAI1.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_RCCEx_DisablePLLSAI1(void)
{
 8005154:	b538      	push	{r3, r4, r5, lr}
  uint32_t tickstart = 0U;
  HAL_StatusTypeDef status = HAL_OK;

  /* Disable the PLLSAI1 */
  __HAL_RCC_PLLSAI1_DISABLE();
 8005156:	4c10      	ldr	r4, [pc, #64]	; (8005198 <HAL_RCCEx_DisablePLLSAI1+0x44>)
 8005158:	6823      	ldr	r3, [r4, #0]
 800515a:	f023 6380 	bic.w	r3, r3, #67108864	; 0x4000000
 800515e:	6023      	str	r3, [r4, #0]

  /* Get Start Tick*/
  tickstart = HAL_GetTick();
 8005160:	f7fb fc6a 	bl	8000a38 <HAL_GetTick>
 8005164:	4605      	mov	r5, r0

  /* Wait till PLLSAI1 is ready */
  while(READ_BIT(RCC->CR, RCC_CR_PLLSAI1RDY) != RESET)
 8005166:	6820      	ldr	r0, [r4, #0]
 8005168:	f010 6000 	ands.w	r0, r0, #134217728	; 0x8000000
 800516c:	d005      	beq.n	800517a <HAL_RCCEx_DisablePLLSAI1+0x26>
  {
    if((HAL_GetTick() - tickstart) > PLLSAI1_TIMEOUT_VALUE)
 800516e:	f7fb fc63 	bl	8000a38 <HAL_GetTick>
 8005172:	1b40      	subs	r0, r0, r5
 8005174:	2802      	cmp	r0, #2
 8005176:	d9f6      	bls.n	8005166 <HAL_RCCEx_DisablePLLSAI1+0x12>
    {
      status = HAL_TIMEOUT;
 8005178:	2003      	movs	r0, #3
      break;
    }
  }

  /* Disable the PLLSAI1 Clock outputs */
  __HAL_RCC_PLLSAI1CLKOUT_DISABLE(RCC_PLLSAI1CFGR_PLLSAI1PEN|RCC_PLLSAI1CFGR_PLLSAI1QEN|RCC_PLLSAI1CFGR_PLLSAI1REN);
 800517a:	6923      	ldr	r3, [r4, #16]
 800517c:	4a06      	ldr	r2, [pc, #24]	; (8005198 <HAL_RCCEx_DisablePLLSAI1+0x44>)
 800517e:	f023 7388 	bic.w	r3, r3, #17825792	; 0x1100000
 8005182:	f423 3380 	bic.w	r3, r3, #65536	; 0x10000
 8005186:	6123      	str	r3, [r4, #16]

  /* Reset PLL source to save power if no PLLs on */
  if((READ_BIT(RCC->CR, RCC_CR_PLLRDY) == RESET)
 8005188:	6823      	ldr	r3, [r4, #0]
 800518a:	019b      	lsls	r3, r3, #6
      &&
     (READ_BIT(RCC->CR, RCC_CR_PLLSAI2RDY) == RESET)
#endif /* RCC_PLLSAI2_SUPPORT */
    )
  {
    MODIFY_REG(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC, RCC_PLLSOURCE_NONE);
 800518c:	bf5e      	ittt	pl
 800518e:	68d3      	ldrpl	r3, [r2, #12]
 8005190:	f023 0303 	bicpl.w	r3, r3, #3
 8005194:	60d3      	strpl	r3, [r2, #12]
  }

  return status;
}
 8005196:	bd38      	pop	{r3, r4, r5, pc}
 8005198:	40021000 	.word	0x40021000

0800519c <HAL_RCCEx_WakeUpStopCLKConfig>:
  */
void HAL_RCCEx_WakeUpStopCLKConfig(uint32_t WakeUpClk)
{
  assert_param(IS_RCC_STOP_WAKEUPCLOCK(WakeUpClk));

  __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(WakeUpClk);
 800519c:	4a03      	ldr	r2, [pc, #12]	; (80051ac <HAL_RCCEx_WakeUpStopCLKConfig+0x10>)
 800519e:	6893      	ldr	r3, [r2, #8]
 80051a0:	f423 4300 	bic.w	r3, r3, #32768	; 0x8000
 80051a4:	4318      	orrs	r0, r3
 80051a6:	6090      	str	r0, [r2, #8]
 80051a8:	4770      	bx	lr
 80051aa:	bf00      	nop
 80051ac:	40021000 	.word	0x40021000

080051b0 <HAL_RCCEx_StandbyMSIRangeConfig>:
  */
void HAL_RCCEx_StandbyMSIRangeConfig(uint32_t MSIRange)
{
  assert_param(IS_RCC_MSI_STANDBY_CLOCK_RANGE(MSIRange));

  __HAL_RCC_MSI_STANDBY_RANGE_CONFIG(MSIRange);
 80051b0:	4a04      	ldr	r2, [pc, #16]	; (80051c4 <HAL_RCCEx_StandbyMSIRangeConfig+0x14>)
 80051b2:	f8d2 3094 	ldr.w	r3, [r2, #148]	; 0x94
 80051b6:	f423 6370 	bic.w	r3, r3, #3840	; 0xf00
 80051ba:	ea43 1000 	orr.w	r0, r3, r0, lsl #4
 80051be:	f8c2 0094 	str.w	r0, [r2, #148]	; 0x94
 80051c2:	4770      	bx	lr
 80051c4:	40021000 	.word	0x40021000

080051c8 <HAL_RCCEx_EnableLSECSS>:
  *         clock with HAL_RCCEx_PeriphCLKConfig().
  * @retval None
  */
void HAL_RCCEx_EnableLSECSS(void)
{
  SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
 80051c8:	4a03      	ldr	r2, [pc, #12]	; (80051d8 <HAL_RCCEx_EnableLSECSS+0x10>)
 80051ca:	f8d2 3090 	ldr.w	r3, [r2, #144]	; 0x90
 80051ce:	f043 0320 	orr.w	r3, r3, #32
 80051d2:	f8c2 3090 	str.w	r3, [r2, #144]	; 0x90
 80051d6:	4770      	bx	lr
 80051d8:	40021000 	.word	0x40021000

080051dc <HAL_RCCEx_DisableLSECSS>:
  * @note   LSE Clock Security System can only be disabled after a LSE failure detection.
  * @retval None
  */
void HAL_RCCEx_DisableLSECSS(void)
{
  CLEAR_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
 80051dc:	4b05      	ldr	r3, [pc, #20]	; (80051f4 <HAL_RCCEx_DisableLSECSS+0x18>)
 80051de:	f8d3 2090 	ldr.w	r2, [r3, #144]	; 0x90
 80051e2:	f022 0220 	bic.w	r2, r2, #32
 80051e6:	f8c3 2090 	str.w	r2, [r3, #144]	; 0x90

  /* Disable LSE CSS IT if any */
  __HAL_RCC_DISABLE_IT(RCC_IT_LSECSS);
 80051ea:	699a      	ldr	r2, [r3, #24]
 80051ec:	f422 7200 	bic.w	r2, r2, #512	; 0x200
 80051f0:	619a      	str	r2, [r3, #24]
 80051f2:	4770      	bx	lr
 80051f4:	40021000 	.word	0x40021000

080051f8 <HAL_RCCEx_EnableLSECSS_IT>:
  * @retval None
  */
void HAL_RCCEx_EnableLSECSS_IT(void)
{
  /* Enable LSE CSS */
  SET_BIT(RCC->BDCR, RCC_BDCR_LSECSSON) ;
 80051f8:	4b0a      	ldr	r3, [pc, #40]	; (8005224 <HAL_RCCEx_EnableLSECSS_IT+0x2c>)
 80051fa:	f8d3 2090 	ldr.w	r2, [r3, #144]	; 0x90
 80051fe:	f042 0220 	orr.w	r2, r2, #32
 8005202:	f8c3 2090 	str.w	r2, [r3, #144]	; 0x90

  /* Enable LSE CSS IT */
  __HAL_RCC_ENABLE_IT(RCC_IT_LSECSS);
 8005206:	699a      	ldr	r2, [r3, #24]
 8005208:	f442 7200 	orr.w	r2, r2, #512	; 0x200
 800520c:	619a      	str	r2, [r3, #24]

  /* Enable IT on EXTI Line 19 */
  __HAL_RCC_LSECSS_EXTI_ENABLE_IT();
 800520e:	f5a3 3386 	sub.w	r3, r3, #68608	; 0x10c00
 8005212:	681a      	ldr	r2, [r3, #0]
 8005214:	f442 2200 	orr.w	r2, r2, #524288	; 0x80000
 8005218:	601a      	str	r2, [r3, #0]
  __HAL_RCC_LSECSS_EXTI_ENABLE_RISING_EDGE();
 800521a:	689a      	ldr	r2, [r3, #8]
 800521c:	f442 2200 	orr.w	r2, r2, #524288	; 0x80000
 8005220:	609a      	str	r2, [r3, #8]
 8005222:	4770      	bx	lr
 8005224:	40021000 	.word	0x40021000

08005228 <HAL_RCCEx_LSECSS_Callback>:
/**
  * @brief  RCCEx LSE Clock Security System interrupt callback.
  * @retval none
  */
__weak void HAL_RCCEx_LSECSS_Callback(void)
{
 8005228:	4770      	bx	lr
	...

0800522c <HAL_RCCEx_LSECSS_IRQHandler>:
/**
  * @brief Handle the RCC LSE Clock Security System interrupt request.
  * @retval None
  */
void HAL_RCCEx_LSECSS_IRQHandler(void)
{
 800522c:	b510      	push	{r4, lr}
  /* Check RCC LSE CSSF flag  */
  if(__HAL_RCC_GET_IT(RCC_IT_LSECSS))
 800522e:	4c05      	ldr	r4, [pc, #20]	; (8005244 <HAL_RCCEx_LSECSS_IRQHandler+0x18>)
 8005230:	69e3      	ldr	r3, [r4, #28]
 8005232:	059b      	lsls	r3, r3, #22
 8005234:	d504      	bpl.n	8005240 <HAL_RCCEx_LSECSS_IRQHandler+0x14>
  {
    /* RCC LSE Clock Security System interrupt user callback */
    HAL_RCCEx_LSECSS_Callback();
 8005236:	f7ff fff7 	bl	8005228 <HAL_RCCEx_LSECSS_Callback>

    /* Clear RCC LSE CSS pending bit */
    __HAL_RCC_CLEAR_IT(RCC_IT_LSECSS);
 800523a:	f44f 7300 	mov.w	r3, #512	; 0x200
 800523e:	6223      	str	r3, [r4, #32]
 8005240:	bd10      	pop	{r4, pc}
 8005242:	bf00      	nop
 8005244:	40021000 	.word	0x40021000

08005248 <HAL_RCCEx_EnableMSIPLLMode>:
  *         calibration LSE oscillator is to be enabled with HAL_RCC_OscConfig().
  * @retval None
  */
void HAL_RCCEx_EnableMSIPLLMode(void)
{
  SET_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
 8005248:	4a02      	ldr	r2, [pc, #8]	; (8005254 <HAL_RCCEx_EnableMSIPLLMode+0xc>)
 800524a:	6813      	ldr	r3, [r2, #0]
 800524c:	f043 0304 	orr.w	r3, r3, #4
 8005250:	6013      	str	r3, [r2, #0]
 8005252:	4770      	bx	lr
 8005254:	40021000 	.word	0x40021000

08005258 <HAL_RCCEx_DisableMSIPLLMode>:
  * @note   PLL-mode of the MSI is automatically reset when LSE oscillator is disabled.
  * @retval None
  */
void HAL_RCCEx_DisableMSIPLLMode(void)
{
  CLEAR_BIT(RCC->CR, RCC_CR_MSIPLLEN) ;
 8005258:	4a02      	ldr	r2, [pc, #8]	; (8005264 <HAL_RCCEx_DisableMSIPLLMode+0xc>)
 800525a:	6813      	ldr	r3, [r2, #0]
 800525c:	f023 0304 	bic.w	r3, r3, #4
 8005260:	6013      	str	r3, [r2, #0]
 8005262:	4770      	bx	lr
 8005264:	40021000 	.word	0x40021000

08005268 <sha256_transform>:
	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};

/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
 8005268:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
 800526c:	2200      	movs	r2, #0
	0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};

/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
 800526e:	b0cb      	sub	sp, #300	; 0x12c
 8005270:	460c      	mov	r4, r1
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
 8005272:	5c8d      	ldrb	r5, [r1, r2]
 8005274:	78e3      	ldrb	r3, [r4, #3]
 8005276:	ea43 6305 	orr.w	r3, r3, r5, lsl #24
 800527a:	7865      	ldrb	r5, [r4, #1]
 800527c:	ea43 4305 	orr.w	r3, r3, r5, lsl #16
 8005280:	78a5      	ldrb	r5, [r4, #2]
 8005282:	ea43 2305 	orr.w	r3, r3, r5, lsl #8
 8005286:	ad0a      	add	r5, sp, #40	; 0x28
 8005288:	3404      	adds	r4, #4
 800528a:	50ab      	str	r3, [r5, r2]
/*********************** FUNCTION DEFINITIONS ***********************/
void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
 800528c:	3204      	adds	r2, #4
 800528e:	2a40      	cmp	r2, #64	; 0x40
 8005290:	d1ef      	bne.n	8005272 <sha256_transform+0xa>
 8005292:	462b      	mov	r3, r5
 8005294:	2610      	movs	r6, #16
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
 8005296:	6b9d      	ldr	r5, [r3, #56]	; 0x38
 8005298:	6819      	ldr	r1, [r3, #0]
 800529a:	685a      	ldr	r2, [r3, #4]
 800529c:	ea4f 44f5 	mov.w	r4, r5, ror #19
 80052a0:	ea84 4475 	eor.w	r4, r4, r5, ror #17
 80052a4:	ea84 2595 	eor.w	r5, r4, r5, lsr #10
 80052a8:	6a5c      	ldr	r4, [r3, #36]	; 0x24
 80052aa:	4421      	add	r1, r4
 80052ac:	186c      	adds	r4, r5, r1
 80052ae:	ea4f 41b2 	mov.w	r1, r2, ror #18
 80052b2:	ea81 11f2 	eor.w	r1, r1, r2, ror #7
 80052b6:	ea81 02d2 	eor.w	r2, r1, r2, lsr #3
{
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
 80052ba:	3601      	adds	r6, #1
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
 80052bc:	4422      	add	r2, r4
{
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
 80052be:	2e40      	cmp	r6, #64	; 0x40
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
 80052c0:	641a      	str	r2, [r3, #64]	; 0x40
 80052c2:	f103 0304 	add.w	r3, r3, #4
{
	WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];

	for (i = 0, j = 0; i < 16; ++i, j += 4)
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
 80052c6:	d1e6      	bne.n	8005296 <sha256_transform+0x2e>
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

	a = ctx->state[0];
 80052c8:	6d03      	ldr	r3, [r0, #80]	; 0x50
 80052ca:	9301      	str	r3, [sp, #4]
	b = ctx->state[1];
 80052cc:	6d43      	ldr	r3, [r0, #84]	; 0x54
 80052ce:	9302      	str	r3, [sp, #8]
	c = ctx->state[2];
 80052d0:	6d83      	ldr	r3, [r0, #88]	; 0x58
 80052d2:	9303      	str	r3, [sp, #12]
	d = ctx->state[3];
 80052d4:	6dc3      	ldr	r3, [r0, #92]	; 0x5c
 80052d6:	9304      	str	r3, [sp, #16]
	e = ctx->state[4];
 80052d8:	6e03      	ldr	r3, [r0, #96]	; 0x60
 80052da:	9305      	str	r3, [sp, #20]
	f = ctx->state[5];
 80052dc:	6e43      	ldr	r3, [r0, #100]	; 0x64
 80052de:	9306      	str	r3, [sp, #24]
	g = ctx->state[6];
 80052e0:	6e83      	ldr	r3, [r0, #104]	; 0x68
 80052e2:	9307      	str	r3, [sp, #28]
	h = ctx->state[7];
 80052e4:	6ec3      	ldr	r3, [r0, #108]	; 0x6c
 80052e6:	9308      	str	r3, [sp, #32]
 80052e8:	469b      	mov	fp, r3
	b = ctx->state[1];
	c = ctx->state[2];
	d = ctx->state[3];
	e = ctx->state[4];
	f = ctx->state[5];
	g = ctx->state[6];
 80052ea:	9f07      	ldr	r7, [sp, #28]
	a = ctx->state[0];
	b = ctx->state[1];
	c = ctx->state[2];
	d = ctx->state[3];
	e = ctx->state[4];
	f = ctx->state[5];
 80052ec:	f8dd e018 	ldr.w	lr, [sp, #24]

	a = ctx->state[0];
	b = ctx->state[1];
	c = ctx->state[2];
	d = ctx->state[3];
	e = ctx->state[4];
 80052f0:	9b05      	ldr	r3, [sp, #20]
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

	a = ctx->state[0];
	b = ctx->state[1];
	c = ctx->state[2];
	d = ctx->state[3];
 80052f2:	f8dd 8010 	ldr.w	r8, [sp, #16]
	for ( ; i < 64; ++i)
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

	a = ctx->state[0];
	b = ctx->state[1];
	c = ctx->state[2];
 80052f6:	9d03      	ldr	r5, [sp, #12]
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

	a = ctx->state[0];
	b = ctx->state[1];
 80052f8:	9e02      	ldr	r6, [sp, #8]
	for (i = 0, j = 0; i < 16; ++i, j += 4)
		m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
	for ( ; i < 64; ++i)
		m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];

	a = ctx->state[0];
 80052fa:	9901      	ldr	r1, [sp, #4]
	f = ctx->state[5];
	g = ctx->state[6];
	h = ctx->state[7];

	for (i = 0; i < 64; ++i) {
		t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
 80052fc:	f8df 90ac 	ldr.w	r9, [pc, #172]	; 80053ac <sha256_transform+0x144>
	e = ctx->state[4];
	f = ctx->state[5];
	g = ctx->state[6];
	h = ctx->state[7];

	for (i = 0; i < 64; ++i) {
 8005300:	f04f 0c00 	mov.w	ip, #0
		t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
 8005304:	ea4f 22f3 	mov.w	r2, r3, ror #11
 8005308:	ea82 12b3 	eor.w	r2, r2, r3, ror #6
 800530c:	ea82 6a73 	eor.w	sl, r2, r3, ror #25
 8005310:	aa0a      	add	r2, sp, #40	; 0x28
 8005312:	f852 402c 	ldr.w	r4, [r2, ip, lsl #2]
 8005316:	4622      	mov	r2, r4
 8005318:	f859 402c 	ldr.w	r4, [r9, ip, lsl #2]
 800531c:	4414      	add	r4, r2
 800531e:	eb0a 0204 	add.w	r2, sl, r4
 8005322:	ea03 0a0e 	and.w	sl, r3, lr
 8005326:	ea27 0403 	bic.w	r4, r7, r3
 800532a:	ea84 040a 	eor.w	r4, r4, sl
 800532e:	4414      	add	r4, r2
 8005330:	445c      	add	r4, fp
		t2 = EP0(a) + MAJ(a,b,c);
 8005332:	ea4f 3a71 	mov.w	sl, r1, ror #13
 8005336:	ea85 0b06 	eor.w	fp, r5, r6
 800533a:	ea0b 0b01 	and.w	fp, fp, r1
 800533e:	ea8a 0ab1 	eor.w	sl, sl, r1, ror #2
 8005342:	ea06 0205 	and.w	r2, r6, r5
 8005346:	ea8b 0202 	eor.w	r2, fp, r2
 800534a:	ea8a 5ab1 	eor.w	sl, sl, r1, ror #22
	e = ctx->state[4];
	f = ctx->state[5];
	g = ctx->state[6];
	h = ctx->state[7];

	for (i = 0; i < 64; ++i) {
 800534e:	f10c 0c01 	add.w	ip, ip, #1
		t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
		t2 = EP0(a) + MAJ(a,b,c);
 8005352:	4492      	add	sl, r2
	e = ctx->state[4];
	f = ctx->state[5];
	g = ctx->state[6];
	h = ctx->state[7];

	for (i = 0; i < 64; ++i) {
 8005354:	f1bc 0f40 	cmp.w	ip, #64	; 0x40
		t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
		t2 = EP0(a) + MAJ(a,b,c);
		h = g;
		g = f;
		f = e;
		e = d + t1;
 8005358:	eb04 0208 	add.w	r2, r4, r8
 800535c:	9209      	str	r2, [sp, #36]	; 0x24
		d = c;
		c = b;
		b = a;
		a = t1 + t2;
 800535e:	4454      	add	r4, sl
 8005360:	46a8      	mov	r8, r5
 8005362:	46bb      	mov	fp, r7
	e = ctx->state[4];
	f = ctx->state[5];
	g = ctx->state[6];
	h = ctx->state[7];

	for (i = 0; i < 64; ++i) {
 8005364:	d006      	beq.n	8005374 <sha256_transform+0x10c>
 8005366:	4677      	mov	r7, lr
 8005368:	4635      	mov	r5, r6
 800536a:	469e      	mov	lr, r3
 800536c:	460e      	mov	r6, r1
		t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
		t2 = EP0(a) + MAJ(a,b,c);
		h = g;
		g = f;
		f = e;
		e = d + t1;
 800536e:	9b09      	ldr	r3, [sp, #36]	; 0x24
		d = c;
		c = b;
		b = a;
		a = t1 + t2;
 8005370:	4621      	mov	r1, r4
 8005372:	e7c7      	b.n	8005304 <sha256_transform+0x9c>
	}

	ctx->state[0] += a;
 8005374:	9a01      	ldr	r2, [sp, #4]
 8005376:	4422      	add	r2, r4
 8005378:	6502      	str	r2, [r0, #80]	; 0x50
	ctx->state[1] += b;
 800537a:	9a02      	ldr	r2, [sp, #8]
 800537c:	440a      	add	r2, r1
 800537e:	6542      	str	r2, [r0, #84]	; 0x54
	ctx->state[2] += c;
 8005380:	9a03      	ldr	r2, [sp, #12]
	ctx->state[3] += d;
	ctx->state[4] += e;
 8005382:	9909      	ldr	r1, [sp, #36]	; 0x24
		a = t1 + t2;
	}

	ctx->state[0] += a;
	ctx->state[1] += b;
	ctx->state[2] += c;
 8005384:	4432      	add	r2, r6
 8005386:	6582      	str	r2, [r0, #88]	; 0x58
	ctx->state[3] += d;
 8005388:	9a04      	ldr	r2, [sp, #16]
 800538a:	442a      	add	r2, r5
 800538c:	65c2      	str	r2, [r0, #92]	; 0x5c
	ctx->state[4] += e;
 800538e:	9a05      	ldr	r2, [sp, #20]
 8005390:	440a      	add	r2, r1
 8005392:	6602      	str	r2, [r0, #96]	; 0x60
	ctx->state[5] += f;
 8005394:	9a06      	ldr	r2, [sp, #24]
 8005396:	441a      	add	r2, r3
	ctx->state[6] += g;
 8005398:	9b07      	ldr	r3, [sp, #28]
	ctx->state[0] += a;
	ctx->state[1] += b;
	ctx->state[2] += c;
	ctx->state[3] += d;
	ctx->state[4] += e;
	ctx->state[5] += f;
 800539a:	6642      	str	r2, [r0, #100]	; 0x64
	ctx->state[6] += g;
 800539c:	4473      	add	r3, lr
 800539e:	6683      	str	r3, [r0, #104]	; 0x68
	ctx->state[7] += h;
 80053a0:	9b08      	ldr	r3, [sp, #32]
 80053a2:	443b      	add	r3, r7
 80053a4:	66c3      	str	r3, [r0, #108]	; 0x6c
}
 80053a6:	b04b      	add	sp, #300	; 0x12c
 80053a8:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 80053ac:	080073d4 	.word	0x080073d4

080053b0 <sha256_init>:

void sha256_init(SHA256_CTX *ctx)
{
	ctx->datalen = 0;
 80053b0:	2300      	movs	r3, #0
 80053b2:	6403      	str	r3, [r0, #64]	; 0x40
	ctx->bitlen = 0;
 80053b4:	2200      	movs	r2, #0
 80053b6:	2300      	movs	r3, #0
 80053b8:	e9c0 2312 	strd	r2, r3, [r0, #72]	; 0x48
	ctx->state[0] = 0x6a09e667;
 80053bc:	4b0a      	ldr	r3, [pc, #40]	; (80053e8 <sha256_init+0x38>)
 80053be:	6503      	str	r3, [r0, #80]	; 0x50
	ctx->state[1] = 0xbb67ae85;
 80053c0:	4b0a      	ldr	r3, [pc, #40]	; (80053ec <sha256_init+0x3c>)
 80053c2:	6543      	str	r3, [r0, #84]	; 0x54
	ctx->state[2] = 0x3c6ef372;
 80053c4:	4b0a      	ldr	r3, [pc, #40]	; (80053f0 <sha256_init+0x40>)
 80053c6:	6583      	str	r3, [r0, #88]	; 0x58
	ctx->state[3] = 0xa54ff53a;
 80053c8:	4b0a      	ldr	r3, [pc, #40]	; (80053f4 <sha256_init+0x44>)
 80053ca:	65c3      	str	r3, [r0, #92]	; 0x5c
	ctx->state[4] = 0x510e527f;
 80053cc:	4b0a      	ldr	r3, [pc, #40]	; (80053f8 <sha256_init+0x48>)
 80053ce:	6603      	str	r3, [r0, #96]	; 0x60
	ctx->state[5] = 0x9b05688c;
 80053d0:	4b0a      	ldr	r3, [pc, #40]	; (80053fc <sha256_init+0x4c>)
 80053d2:	6643      	str	r3, [r0, #100]	; 0x64
	ctx->state[6] = 0x1f83d9ab;
 80053d4:	4b0a      	ldr	r3, [pc, #40]	; (8005400 <sha256_init+0x50>)
 80053d6:	6683      	str	r3, [r0, #104]	; 0x68
	ctx->state[7] = 0x5be0cd19;
 80053d8:	f103 5374 	add.w	r3, r3, #1023410176	; 0x3d000000
 80053dc:	f5a3 0323 	sub.w	r3, r3, #10682368	; 0xa30000
 80053e0:	f6a3 4392 	subw	r3, r3, #3218	; 0xc92
 80053e4:	66c3      	str	r3, [r0, #108]	; 0x6c
 80053e6:	4770      	bx	lr
 80053e8:	6a09e667 	.word	0x6a09e667
 80053ec:	bb67ae85 	.word	0xbb67ae85
 80053f0:	3c6ef372 	.word	0x3c6ef372
 80053f4:	a54ff53a 	.word	0xa54ff53a
 80053f8:	510e527f 	.word	0x510e527f
 80053fc:	9b05688c 	.word	0x9b05688c
 8005400:	1f83d9ab 	.word	0x1f83d9ab

08005404 <sha256_update>:
}

void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
 8005404:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
 8005406:	4604      	mov	r4, r0
 8005408:	460d      	mov	r5, r1
 800540a:	188e      	adds	r6, r1, r2
		ctx->data[ctx->datalen] = data[i];
		ctx->datalen++;
		if (ctx->datalen == 64) {
			sha256_transform(ctx, ctx->data);
			ctx->bitlen += 512;
			ctx->datalen = 0;
 800540c:	2700      	movs	r7, #0

void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
	WORD i;

	for (i = 0; i < len; ++i) {
 800540e:	42b5      	cmp	r5, r6
 8005410:	d015      	beq.n	800543e <sha256_update+0x3a>
		ctx->data[ctx->datalen] = data[i];
 8005412:	6c23      	ldr	r3, [r4, #64]	; 0x40
 8005414:	f815 2b01 	ldrb.w	r2, [r5], #1
 8005418:	54e2      	strb	r2, [r4, r3]
		ctx->datalen++;
 800541a:	3301      	adds	r3, #1
		if (ctx->datalen == 64) {
 800541c:	2b40      	cmp	r3, #64	; 0x40
{
	WORD i;

	for (i = 0; i < len; ++i) {
		ctx->data[ctx->datalen] = data[i];
		ctx->datalen++;
 800541e:	6423      	str	r3, [r4, #64]	; 0x40
		if (ctx->datalen == 64) {
 8005420:	d1f5      	bne.n	800540e <sha256_update+0xa>
			sha256_transform(ctx, ctx->data);
 8005422:	4621      	mov	r1, r4
 8005424:	4620      	mov	r0, r4
 8005426:	f7ff ff1f 	bl	8005268 <sha256_transform>
			ctx->bitlen += 512;
 800542a:	e9d4 0112 	ldrd	r0, r1, [r4, #72]	; 0x48
 800542e:	f510 7000 	adds.w	r0, r0, #512	; 0x200
 8005432:	f141 0100 	adc.w	r1, r1, #0
 8005436:	e9c4 0112 	strd	r0, r1, [r4, #72]	; 0x48
			ctx->datalen = 0;
 800543a:	6427      	str	r7, [r4, #64]	; 0x40
 800543c:	e7e7      	b.n	800540e <sha256_update+0xa>
		}
	}
}
 800543e:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}

08005440 <sha256_final>:

void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
 8005440:	b538      	push	{r3, r4, r5, lr}
	WORD i;

	i = ctx->datalen;
 8005442:	6c03      	ldr	r3, [r0, #64]	; 0x40
 8005444:	2280      	movs	r2, #128	; 0x80

	// Pad whatever data is left in the buffer.
	if (ctx->datalen < 56) {
 8005446:	2b37      	cmp	r3, #55	; 0x37
		}
	}
}

void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
 8005448:	4604      	mov	r4, r0
 800544a:	460d      	mov	r5, r1

	i = ctx->datalen;

	// Pad whatever data is left in the buffer.
	if (ctx->datalen < 56) {
		ctx->data[i++] = 0x80;
 800544c:	54c2      	strb	r2, [r0, r3]
	WORD i;

	i = ctx->datalen;

	// Pad whatever data is left in the buffer.
	if (ctx->datalen < 56) {
 800544e:	d808      	bhi.n	8005462 <sha256_final+0x22>
 8005450:	4403      	add	r3, r0
 8005452:	f100 0237 	add.w	r2, r0, #55	; 0x37
		ctx->data[i++] = 0x80;
		while (i < 56)
			ctx->data[i++] = 0x00;
 8005456:	2100      	movs	r1, #0
	i = ctx->datalen;

	// Pad whatever data is left in the buffer.
	if (ctx->datalen < 56) {
		ctx->data[i++] = 0x80;
		while (i < 56)
 8005458:	429a      	cmp	r2, r3
 800545a:	d014      	beq.n	8005486 <sha256_final+0x46>
			ctx->data[i++] = 0x00;
 800545c:	f803 1f01 	strb.w	r1, [r3, #1]!
 8005460:	e7fa      	b.n	8005458 <sha256_final+0x18>
 8005462:	3301      	adds	r3, #1
 8005464:	4403      	add	r3, r0
	}
	else {
		ctx->data[i++] = 0x80;
		while (i < 64)
			ctx->data[i++] = 0x00;
 8005466:	2100      	movs	r1, #0
		while (i < 56)
			ctx->data[i++] = 0x00;
	}
	else {
		ctx->data[i++] = 0x80;
		while (i < 64)
 8005468:	1b1a      	subs	r2, r3, r4
 800546a:	2a3f      	cmp	r2, #63	; 0x3f
 800546c:	d802      	bhi.n	8005474 <sha256_final+0x34>
			ctx->data[i++] = 0x00;
 800546e:	f803 1b01 	strb.w	r1, [r3], #1
 8005472:	e7f9      	b.n	8005468 <sha256_final+0x28>
		sha256_transform(ctx, ctx->data);
 8005474:	4621      	mov	r1, r4
 8005476:	4620      	mov	r0, r4
 8005478:	f7ff fef6 	bl	8005268 <sha256_transform>
		memset(ctx->data, 0, 56);
 800547c:	2238      	movs	r2, #56	; 0x38
 800547e:	2100      	movs	r1, #0
 8005480:	4620      	mov	r0, r4
 8005482:	f001 fa37 	bl	80068f4 <memset>
	}

	// Append to the padding the total message's length in bits and transform.
	ctx->bitlen += ctx->datalen * 8;
 8005486:	6c23      	ldr	r3, [r4, #64]	; 0x40
 8005488:	00d9      	lsls	r1, r3, #3
 800548a:	e9d4 2312 	ldrd	r2, r3, [r4, #72]	; 0x48
 800548e:	1852      	adds	r2, r2, r1
 8005490:	f143 0300 	adc.w	r3, r3, #0
	ctx->data[63] = ctx->bitlen;
	ctx->data[62] = ctx->bitlen >> 8;
 8005494:	0a11      	lsrs	r1, r2, #8
		sha256_transform(ctx, ctx->data);
		memset(ctx->data, 0, 56);
	}

	// Append to the padding the total message's length in bits and transform.
	ctx->bitlen += ctx->datalen * 8;
 8005496:	e9c4 2312 	strd	r2, r3, [r4, #72]	; 0x48
	ctx->data[63] = ctx->bitlen;
 800549a:	f884 203f 	strb.w	r2, [r4, #63]	; 0x3f
	ctx->data[62] = ctx->bitlen >> 8;
 800549e:	f884 103e 	strb.w	r1, [r4, #62]	; 0x3e
	ctx->data[61] = ctx->bitlen >> 16;
 80054a2:	0c11      	lsrs	r1, r2, #16
	ctx->data[60] = ctx->bitlen >> 24;
 80054a4:	0e12      	lsrs	r2, r2, #24
 80054a6:	f884 203c 	strb.w	r2, [r4, #60]	; 0x3c
	ctx->data[59] = ctx->bitlen >> 32;
	ctx->data[58] = ctx->bitlen >> 40;
 80054aa:	0a1a      	lsrs	r2, r3, #8
	ctx->bitlen += ctx->datalen * 8;
	ctx->data[63] = ctx->bitlen;
	ctx->data[62] = ctx->bitlen >> 8;
	ctx->data[61] = ctx->bitlen >> 16;
	ctx->data[60] = ctx->bitlen >> 24;
	ctx->data[59] = ctx->bitlen >> 32;
 80054ac:	f884 303b 	strb.w	r3, [r4, #59]	; 0x3b
	ctx->data[58] = ctx->bitlen >> 40;
 80054b0:	f884 203a 	strb.w	r2, [r4, #58]	; 0x3a
	ctx->data[57] = ctx->bitlen >> 48;
 80054b4:	0c1a      	lsrs	r2, r3, #16
	ctx->data[56] = ctx->bitlen >> 56;
 80054b6:	0e1b      	lsrs	r3, r3, #24

	// Append to the padding the total message's length in bits and transform.
	ctx->bitlen += ctx->datalen * 8;
	ctx->data[63] = ctx->bitlen;
	ctx->data[62] = ctx->bitlen >> 8;
	ctx->data[61] = ctx->bitlen >> 16;
 80054b8:	f884 103d 	strb.w	r1, [r4, #61]	; 0x3d
	ctx->data[60] = ctx->bitlen >> 24;
	ctx->data[59] = ctx->bitlen >> 32;
	ctx->data[58] = ctx->bitlen >> 40;
	ctx->data[57] = ctx->bitlen >> 48;
 80054bc:	f884 2039 	strb.w	r2, [r4, #57]	; 0x39
	ctx->data[56] = ctx->bitlen >> 56;
 80054c0:	f884 3038 	strb.w	r3, [r4, #56]	; 0x38
	sha256_transform(ctx, ctx->data);
 80054c4:	4621      	mov	r1, r4
 80054c6:	4620      	mov	r0, r4
 80054c8:	f7ff fece 	bl	8005268 <sha256_transform>
 80054cc:	2203      	movs	r2, #3

	// Since this implementation uses little endian byte ordering and SHA uses big endian,
	// reverse all the bytes when copying the final state to the output hash.
	for (i = 0; i < 4; ++i) {
		hash[i]      = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
 80054ce:	6d21      	ldr	r1, [r4, #80]	; 0x50
 80054d0:	00d3      	lsls	r3, r2, #3
 80054d2:	40d9      	lsrs	r1, r3
 80054d4:	7029      	strb	r1, [r5, #0]
		hash[i + 4]  = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
 80054d6:	6d61      	ldr	r1, [r4, #84]	; 0x54
 80054d8:	40d9      	lsrs	r1, r3
 80054da:	7129      	strb	r1, [r5, #4]
		hash[i + 8]  = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
 80054dc:	6da1      	ldr	r1, [r4, #88]	; 0x58
 80054de:	40d9      	lsrs	r1, r3
 80054e0:	7229      	strb	r1, [r5, #8]
		hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
 80054e2:	6de1      	ldr	r1, [r4, #92]	; 0x5c
 80054e4:	40d9      	lsrs	r1, r3
 80054e6:	7329      	strb	r1, [r5, #12]
		hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
 80054e8:	6e21      	ldr	r1, [r4, #96]	; 0x60
 80054ea:	40d9      	lsrs	r1, r3
 80054ec:	7429      	strb	r1, [r5, #16]
		hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
 80054ee:	6e61      	ldr	r1, [r4, #100]	; 0x64
 80054f0:	40d9      	lsrs	r1, r3
 80054f2:	7529      	strb	r1, [r5, #20]
		hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
 80054f4:	6ea1      	ldr	r1, [r4, #104]	; 0x68
 80054f6:	40d9      	lsrs	r1, r3
 80054f8:	7629      	strb	r1, [r5, #24]
		hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
 80054fa:	6ee1      	ldr	r1, [r4, #108]	; 0x6c
 80054fc:	3a01      	subs	r2, #1
 80054fe:	fa21 f303 	lsr.w	r3, r1, r3
 8005502:	772b      	strb	r3, [r5, #28]
	ctx->data[56] = ctx->bitlen >> 56;
	sha256_transform(ctx, ctx->data);

	// Since this implementation uses little endian byte ordering and SHA uses big endian,
	// reverse all the bytes when copying the final state to the output hash.
	for (i = 0; i < 4; ++i) {
 8005504:	1c53      	adds	r3, r2, #1
 8005506:	f105 0501 	add.w	r5, r5, #1
 800550a:	d1e0      	bne.n	80054ce <sha256_final+0x8e>
		hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
		hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
		hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
		hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
	}
}
 800550c:	bd38      	pop	{r3, r4, r5, pc}

0800550e <uECC_vli_mult>:

#if !asm_mult
uECC_VLI_API void uECC_vli_mult(uECC_word_t *result,
                                const uECC_word_t *left,
                                const uECC_word_t *right,
                                wordcount_t num_words) {
 800550e:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
    );
    
#else /* Thumb-1 */
    uint32_t r4, r5, r6, r7;

    __asm__ volatile (
 8005512:	3b01      	subs	r3, #1
 8005514:	009b      	lsls	r3, r3, #2
 8005516:	4698      	mov	r8, r3
 8005518:	005b      	lsls	r3, r3, #1
 800551a:	4699      	mov	r9, r3
 800551c:	2300      	movs	r3, #0
 800551e:	2400      	movs	r4, #0
 8005520:	2500      	movs	r5, #0
 8005522:	2600      	movs	r6, #0
 8005524:	b401      	push	{r0}
 8005526:	2700      	movs	r7, #0
 8005528:	e002      	b.n	8005530 <uECC_vli_mult+0x22>
 800552a:	0037      	movs	r7, r6
 800552c:	4640      	mov	r0, r8
 800552e:	1a3f      	subs	r7, r7, r0
 8005530:	b478      	push	{r3, r4, r5, r6}
 8005532:	1bf0      	subs	r0, r6, r7
 8005534:	5814      	ldr	r4, [r2, r0]
 8005536:	59c8      	ldr	r0, [r1, r7]
 8005538:	0c03      	lsrs	r3, r0, #16
 800553a:	b280      	uxth	r0, r0
 800553c:	0c25      	lsrs	r5, r4, #16
 800553e:	b2a4      	uxth	r4, r4
 8005540:	001e      	movs	r6, r3
 8005542:	436e      	muls	r6, r5
 8005544:	4363      	muls	r3, r4
 8005546:	4345      	muls	r5, r0
 8005548:	4360      	muls	r0, r4
 800554a:	2400      	movs	r4, #0
 800554c:	195b      	adds	r3, r3, r5
 800554e:	4164      	adcs	r4, r4
 8005550:	0424      	lsls	r4, r4, #16
 8005552:	1936      	adds	r6, r6, r4
 8005554:	041c      	lsls	r4, r3, #16
 8005556:	0c1b      	lsrs	r3, r3, #16
 8005558:	1900      	adds	r0, r0, r4
 800555a:	415e      	adcs	r6, r3
 800555c:	bc38      	pop	{r3, r4, r5}
 800555e:	181b      	adds	r3, r3, r0
 8005560:	4174      	adcs	r4, r6
 8005562:	2000      	movs	r0, #0
 8005564:	4145      	adcs	r5, r0
 8005566:	bc40      	pop	{r6}
 8005568:	3704      	adds	r7, #4
 800556a:	4547      	cmp	r7, r8
 800556c:	dc01      	bgt.n	8005572 <uECC_vli_mult+0x64>
 800556e:	42b7      	cmp	r7, r6
 8005570:	ddde      	ble.n	8005530 <uECC_vli_mult+0x22>
 8005572:	9800      	ldr	r0, [sp, #0]
 8005574:	5183      	str	r3, [r0, r6]
 8005576:	4623      	mov	r3, r4
 8005578:	462c      	mov	r4, r5
 800557a:	2500      	movs	r5, #0
 800557c:	3604      	adds	r6, #4
 800557e:	4546      	cmp	r6, r8
 8005580:	ddd1      	ble.n	8005526 <uECC_vli_mult+0x18>
 8005582:	454e      	cmp	r6, r9
 8005584:	ddd1      	ble.n	800552a <uECC_vli_mult+0x1c>
 8005586:	5183      	str	r3, [r0, r6]
 8005588:	bc01      	pop	{r0}
 800558a:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}

0800558e <uECC_vli_clear>:
}

#if !asm_clear
uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
 800558e:	2200      	movs	r2, #0
void uECC_set_rng(uECC_RNG_Function rng_function) {
    g_rng_function = rng_function;
}

#if !asm_clear
uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
 8005590:	b510      	push	{r4, lr}
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
        vli[i] = 0;
 8005592:	4614      	mov	r4, r2
}

#if !asm_clear
uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) {
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
 8005594:	b253      	sxtb	r3, r2
 8005596:	428b      	cmp	r3, r1
 8005598:	da04      	bge.n	80055a4 <uECC_vli_clear+0x16>
        vli[i] = 0;
 800559a:	b21b      	sxth	r3, r3
 800559c:	3201      	adds	r2, #1
 800559e:	f840 4023 	str.w	r4, [r0, r3, lsl #2]
 80055a2:	e7f7      	b.n	8005594 <uECC_vli_clear+0x6>
    }
}
 80055a4:	bd10      	pop	{r4, pc}

080055a6 <uECC_vli_isZero>:
#endif /* !asm_clear */

/* Constant-time comparison to zero - secure way to compare long integers */
/* Returns 1 if vli == 0, 0 otherwise. */
uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) {
 80055a6:	b510      	push	{r4, lr}
    uECC_word_t bits = 0;
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
 80055a8:	2300      	movs	r3, #0
#endif /* !asm_clear */

/* Constant-time comparison to zero - secure way to compare long integers */
/* Returns 1 if vli == 0, 0 otherwise. */
uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) {
    uECC_word_t bits = 0;
 80055aa:	461a      	mov	r2, r3
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
 80055ac:	b25c      	sxtb	r4, r3
 80055ae:	428c      	cmp	r4, r1
 80055b0:	da04      	bge.n	80055bc <uECC_vli_isZero+0x16>
        bits |= vli[i];
 80055b2:	f850 4024 	ldr.w	r4, [r0, r4, lsl #2]
 80055b6:	3301      	adds	r3, #1
 80055b8:	4322      	orrs	r2, r4
 80055ba:	e7f7      	b.n	80055ac <uECC_vli_isZero+0x6>
    }
    return (bits == 0);
}
 80055bc:	fab2 f082 	clz	r0, r2
 80055c0:	0940      	lsrs	r0, r0, #5
 80055c2:	bd10      	pop	{r4, pc}

080055c4 <uECC_vli_testBit>:

/* Returns nonzero if bit 'bit' of vli is set. */
uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) {
    return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
 80055c4:	114a      	asrs	r2, r1, #5
 80055c6:	2301      	movs	r3, #1
 80055c8:	f850 0022 	ldr.w	r0, [r0, r2, lsl #2]
 80055cc:	f001 011f 	and.w	r1, r1, #31
 80055d0:	fa03 f101 	lsl.w	r1, r3, r1
}
 80055d4:	4008      	ands	r0, r1
 80055d6:	4770      	bx	lr

080055d8 <uECC_vli_numBits>:

    return (i + 1);
}

/* Counts the number of bits required to represent vli. */
uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) {
 80055d8:	3901      	subs	r1, #1
 80055da:	b2c9      	uxtb	r1, r1
/* Counts the number of words in vli. */
static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) {
    wordcount_t i;
    /* Search from the end until we find a non-zero digit.
       We do it in reverse because we expect that most digits will be nonzero. */
    for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
 80055dc:	b24b      	sxtb	r3, r1
 80055de:	2b00      	cmp	r3, #0
 80055e0:	da0b      	bge.n	80055fa <uECC_vli_numBits+0x22>
    }

    return (i + 1);
 80055e2:	3101      	adds	r1, #1
uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) {
    uECC_word_t i;
    uECC_word_t digit;

    wordcount_t num_digits = vli_numDigits(vli, max_words);
    if (num_digits == 0) {
 80055e4:	f011 03ff 	ands.w	r3, r1, #255	; 0xff
 80055e8:	d015      	beq.n	8005616 <uECC_vli_numBits+0x3e>
        return 0;
    }

    digit = vli[num_digits - 1];
 80055ea:	b259      	sxtb	r1, r3
 80055ec:	f101 4380 	add.w	r3, r1, #1073741824	; 0x40000000
 80055f0:	3b01      	subs	r3, #1
 80055f2:	f850 2023 	ldr.w	r2, [r0, r3, lsl #2]
    for (i = 0; digit; ++i) {
 80055f6:	2300      	movs	r3, #0
 80055f8:	e004      	b.n	8005604 <uECC_vli_numBits+0x2c>
/* Counts the number of words in vli. */
static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) {
    wordcount_t i;
    /* Search from the end until we find a non-zero digit.
       We do it in reverse because we expect that most digits will be nonzero. */
    for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
 80055fa:	f850 3023 	ldr.w	r3, [r0, r3, lsl #2]
 80055fe:	2b00      	cmp	r3, #0
 8005600:	d0ea      	beq.n	80055d8 <uECC_vli_numBits>
 8005602:	e7ee      	b.n	80055e2 <uECC_vli_numBits+0xa>
    if (num_digits == 0) {
        return 0;
    }

    digit = vli[num_digits - 1];
    for (i = 0; digit; ++i) {
 8005604:	b112      	cbz	r2, 800560c <uECC_vli_numBits+0x34>
        digit >>= 1;
 8005606:	0852      	lsrs	r2, r2, #1
    if (num_digits == 0) {
        return 0;
    }

    digit = vli[num_digits - 1];
    for (i = 0; digit; ++i) {
 8005608:	3301      	adds	r3, #1
 800560a:	e7fb      	b.n	8005604 <uECC_vli_numBits+0x2c>
        digit >>= 1;
    }

    return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
 800560c:	1e48      	subs	r0, r1, #1
 800560e:	eb03 1040 	add.w	r0, r3, r0, lsl #5
 8005612:	b280      	uxth	r0, r0
 8005614:	e000      	b.n	8005618 <uECC_vli_numBits+0x40>
    uECC_word_t i;
    uECC_word_t digit;

    wordcount_t num_digits = vli_numDigits(vli, max_words);
    if (num_digits == 0) {
        return 0;
 8005616:	4618      	mov	r0, r3
    for (i = 0; digit; ++i) {
        digit >>= 1;
    }

    return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
}
 8005618:	b200      	sxth	r0, r0
 800561a:	4770      	bx	lr

0800561c <uECC_vli_set>:

/* Sets dest = src. */
#if !asm_set
uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
 800561c:	b530      	push	{r4, r5, lr}
    wordcount_t i;
    for (i = 0; i < num_words; ++i) {
 800561e:	2400      	movs	r4, #0
 8005620:	b263      	sxtb	r3, r4
 8005622:	4293      	cmp	r3, r2
 8005624:	da06      	bge.n	8005634 <uECC_vli_set+0x18>
        dest[i] = src[i];
 8005626:	b21b      	sxth	r3, r3
 8005628:	3401      	adds	r4, #1
 800562a:	f851 5023 	ldr.w	r5, [r1, r3, lsl #2]
 800562e:	f840 5023 	str.w	r5, [r0, r3, lsl #2]
 8005632:	e7f5      	b.n	8005620 <uECC_vli_set+0x4>
    }
}
 8005634:	bd30      	pop	{r4, r5, pc}

08005636 <uECC_vli_cmp_unsafe>:
#endif /* !asm_set */

/* Returns sign of left - right. */
static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
                                       const uECC_word_t *right,
                                       wordcount_t num_words) {
 8005636:	b510      	push	{r4, lr}
 8005638:	3a01      	subs	r2, #1
 800563a:	b2d2      	uxtb	r2, r2
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
 800563c:	b253      	sxtb	r3, r2
 800563e:	2b00      	cmp	r3, #0
 8005640:	db09      	blt.n	8005656 <uECC_vli_cmp_unsafe+0x20>
        if (left[i] > right[i]) {
 8005642:	b21b      	sxth	r3, r3
 8005644:	f850 4023 	ldr.w	r4, [r0, r3, lsl #2]
 8005648:	f851 3023 	ldr.w	r3, [r1, r3, lsl #2]
 800564c:	429c      	cmp	r4, r3
 800564e:	d804      	bhi.n	800565a <uECC_vli_cmp_unsafe+0x24>
            return 1;
        } else if (left[i] < right[i]) {
 8005650:	d2f2      	bcs.n	8005638 <uECC_vli_cmp_unsafe+0x2>
            return -1;
 8005652:	20ff      	movs	r0, #255	; 0xff
 8005654:	e002      	b.n	800565c <uECC_vli_cmp_unsafe+0x26>
        }
    }
    return 0;
 8005656:	2000      	movs	r0, #0
 8005658:	e000      	b.n	800565c <uECC_vli_cmp_unsafe+0x26>
                                       const uECC_word_t *right,
                                       wordcount_t num_words) {
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
        if (left[i] > right[i]) {
            return 1;
 800565a:	2001      	movs	r0, #1
        } else if (left[i] < right[i]) {
            return -1;
        }
    }
    return 0;
}
 800565c:	b240      	sxtb	r0, r0
 800565e:	bd10      	pop	{r4, pc}

08005660 <uECC_vli_rshift1>:
    return (!equal - 2 * neg);
}

/* Computes vli = vli >> 1. */
#if !asm_rshift1
uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
 8005660:	eb00 0181 	add.w	r1, r0, r1, lsl #2
    uECC_word_t *end = vli;
    uECC_word_t carry = 0;
 8005664:	2300      	movs	r3, #0
    
    vli += num_words;
    while (vli-- > end) {
 8005666:	4288      	cmp	r0, r1
 8005668:	d206      	bcs.n	8005678 <uECC_vli_rshift1+0x18>
        uECC_word_t temp = *vli;
 800566a:	f851 2d04 	ldr.w	r2, [r1, #-4]!
        *vli = (temp >> 1) | carry;
 800566e:	ea43 0352 	orr.w	r3, r3, r2, lsr #1
 8005672:	600b      	str	r3, [r1, #0]
        carry = temp << (uECC_WORD_BITS - 1);
 8005674:	07d3      	lsls	r3, r2, #31
 8005676:	e7f6      	b.n	8005666 <uECC_vli_rshift1+0x6>
    }
}
 8005678:	4770      	bx	lr
	...

0800567c <uECC_vli_modMult>:
/* Computes result = (left * right) % mod. */
uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result,
                                   const uECC_word_t *left,
                                   const uECC_word_t *right,
                                   const uECC_word_t *mod,
                                   wordcount_t num_words) {
 800567c:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
 8005680:	b0b5      	sub	sp, #212	; 0xd4
    uECC_word_t product[2 * uECC_MAX_WORDS];
    uECC_vli_mult(product, left, right, num_words);
 8005682:	ad04      	add	r5, sp, #16
/* Computes result = (left * right) % mod. */
uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result,
                                   const uECC_word_t *left,
                                   const uECC_word_t *right,
                                   const uECC_word_t *mod,
                                   wordcount_t num_words) {
 8005684:	f99d 40f8 	ldrsb.w	r4, [sp, #248]	; 0xf8
 8005688:	4699      	mov	r9, r3
 800568a:	4680      	mov	r8, r0
    uECC_word_t product[2 * uECC_MAX_WORDS];
    uECC_vli_mult(product, left, right, num_words);
 800568c:	4623      	mov	r3, r4
 800568e:	4628      	mov	r0, r5
 8005690:	f7ff ff3d 	bl	800550e <uECC_vli_mult>
                                uECC_word_t *product,
                                const uECC_word_t *mod,
                                wordcount_t num_words) {
    uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
    uECC_word_t tmp[2 * uECC_MAX_WORDS];
    uECC_word_t *v[2] = {tmp, product};
 8005694:	ab24      	add	r3, sp, #144	; 0x90
    uECC_word_t index;
    
    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
 8005696:	4621      	mov	r1, r4
 8005698:	4648      	mov	r0, r9
                                uECC_word_t *product,
                                const uECC_word_t *mod,
                                wordcount_t num_words) {
    uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
    uECC_word_t tmp[2 * uECC_MAX_WORDS];
    uECC_word_t *v[2] = {tmp, product};
 800569a:	9302      	str	r3, [sp, #8]
 800569c:	9503      	str	r5, [sp, #12]
    uECC_word_t index;
    
    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
 800569e:	f7ff ff9b 	bl	80055d8 <uECC_vli_numBits>
 80056a2:	ebc0 1084 	rsb	r0, r0, r4, lsl #6
 80056a6:	b285      	uxth	r5, r0
    wordcount_t word_shift = shift / uECC_WORD_BITS;
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
 80056a8:	4b49      	ldr	r3, [pc, #292]	; (80057d0 <uECC_vli_modMult+0x154>)
    uECC_word_t *v[2] = {tmp, product};
    uECC_word_t index;
    
    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
    wordcount_t word_shift = shift / uECC_WORD_BITS;
 80056aa:	b22a      	sxth	r2, r5
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
 80056ac:	4013      	ands	r3, r2
 80056ae:	2b00      	cmp	r3, #0
 80056b0:	bfbc      	itt	lt
 80056b2:	f103 33ff 	addlt.w	r3, r3, #4294967295	; 0xffffffff
 80056b6:	f063 031f 	ornlt	r3, r3, #31
    uECC_word_t *v[2] = {tmp, product};
    uECC_word_t index;
    
    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
    wordcount_t word_shift = shift / uECC_WORD_BITS;
 80056ba:	f04f 0720 	mov.w	r7, #32
 80056be:	fb92 f7f7 	sdiv	r7, r2, r7
 80056c2:	b2ff      	uxtb	r7, r7
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
 80056c4:	bfb8      	it	lt
 80056c6:	3301      	addlt	r3, #1
    uECC_word_t carry = 0;
    uECC_vli_clear(mod_multiple, word_shift);
 80056c8:	b27f      	sxtb	r7, r7
    uECC_word_t index;
    
    /* Shift mod so its highest set bit is at the maximum position. */
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
    wordcount_t word_shift = shift / uECC_WORD_BITS;
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
 80056ca:	b29e      	uxth	r6, r3
    uECC_word_t carry = 0;
    uECC_vli_clear(mod_multiple, word_shift);
 80056cc:	a814      	add	r0, sp, #80	; 0x50
 80056ce:	4639      	mov	r1, r7
 80056d0:	f7ff ff5d 	bl	800558e <uECC_vli_clear>
    if (bit_shift > 0) {
 80056d4:	b233      	sxth	r3, r6
 80056d6:	2b00      	cmp	r3, #0
 80056d8:	b238      	sxth	r0, r7
 80056da:	dd14      	ble.n	8005706 <uECC_vli_modMult+0x8a>
 80056dc:	aa14      	add	r2, sp, #80	; 0x50
 80056de:	2100      	movs	r1, #0
 80056e0:	eb02 0080 	add.w	r0, r2, r0, lsl #2
        for(index = 0; index < (uECC_word_t)num_words; ++index) {
            mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
            carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
 80056e4:	f1c3 0720 	rsb	r7, r3, #32
    bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words);
    wordcount_t word_shift = shift / uECC_WORD_BITS;
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
    uECC_word_t carry = 0;
    uECC_vli_clear(mod_multiple, word_shift);
    if (bit_shift > 0) {
 80056e8:	460a      	mov	r2, r1
        for(index = 0; index < (uECC_word_t)num_words; ++index) {
 80056ea:	42a2      	cmp	r2, r4
 80056ec:	d212      	bcs.n	8005714 <uECC_vli_modMult+0x98>
            mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
 80056ee:	f859 6022 	ldr.w	r6, [r9, r2, lsl #2]
 80056f2:	fa06 fe03 	lsl.w	lr, r6, r3
 80056f6:	ea4e 0101 	orr.w	r1, lr, r1
 80056fa:	f840 1022 	str.w	r1, [r0, r2, lsl #2]
            carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
 80056fe:	fa26 f107 	lsr.w	r1, r6, r7
    wordcount_t word_shift = shift / uECC_WORD_BITS;
    wordcount_t bit_shift = shift % uECC_WORD_BITS;
    uECC_word_t carry = 0;
    uECC_vli_clear(mod_multiple, word_shift);
    if (bit_shift > 0) {
        for(index = 0; index < (uECC_word_t)num_words; ++index) {
 8005702:	3201      	adds	r2, #1
 8005704:	e7f1      	b.n	80056ea <uECC_vli_modMult+0x6e>
            mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
            carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
        }
    } else {
        uECC_vli_set(mod_multiple + word_shift, mod, num_words);
 8005706:	ab14      	add	r3, sp, #80	; 0x50
 8005708:	4622      	mov	r2, r4
 800570a:	4649      	mov	r1, r9
 800570c:	eb03 0080 	add.w	r0, r3, r0, lsl #2
 8005710:	f7ff ff84 	bl	800561c <uECC_vli_set>
 8005714:	b227      	sxth	r7, r4
 8005716:	007b      	lsls	r3, r7, #1
 8005718:	9301      	str	r3, [sp, #4]
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
 800571a:	ab14      	add	r3, sp, #80	; 0x50
 800571c:	eb03 0787 	add.w	r7, r3, r7, lsl #2
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
 8005720:	f104 39ff 	add.w	r9, r4, #4294967295	; 0xffffffff
 8005724:	ab34      	add	r3, sp, #208	; 0xd0
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
 8005726:	2601      	movs	r6, #1
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
 8005728:	eb03 0989 	add.w	r9, r3, r9, lsl #2
        }
    } else {
        uECC_vli_set(mod_multiple + word_shift, mod, num_words);
    }

    for (index = 1; shift >= 0; --shift) {
 800572c:	042b      	lsls	r3, r5, #16
 800572e:	d442      	bmi.n	80057b6 <uECC_vli_modMult+0x13a>
        uECC_word_t borrow = 0;
        wordcount_t i;
        for (i = 0; i < num_words * 2; ++i) {
            uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
 8005730:	ab34      	add	r3, sp, #208	; 0xd0
        }
    } else {
        uECC_vli_set(mod_multiple + word_shift, mod, num_words);
    }

    for (index = 1; shift >= 0; --shift) {
 8005732:	2200      	movs	r2, #0
        for (i = 0; i < num_words * 2; ++i) {
            uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
            if (diff != v[index][i]) {
                borrow = (diff > v[index][i]);
            }
            v[1 - index][i] = diff;
 8005734:	f1c6 0001 	rsb	r0, r6, #1
        }
    } else {
        uECC_vli_set(mod_multiple + word_shift, mod, num_words);
    }

    for (index = 1; shift >= 0; --shift) {
 8005738:	4696      	mov	lr, r2
        uECC_word_t borrow = 0;
        wordcount_t i;
        for (i = 0; i < num_words * 2; ++i) {
            uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
 800573a:	eb03 0a86 	add.w	sl, r3, r6, lsl #2
            if (diff != v[index][i]) {
                borrow = (diff > v[index][i]);
            }
            v[1 - index][i] = diff;
 800573e:	eb03 0080 	add.w	r0, r3, r0, lsl #2
    }

    for (index = 1; shift >= 0; --shift) {
        uECC_word_t borrow = 0;
        wordcount_t i;
        for (i = 0; i < num_words * 2; ++i) {
 8005742:	9b01      	ldr	r3, [sp, #4]
 8005744:	b251      	sxtb	r1, r2
 8005746:	4299      	cmp	r1, r3
 8005748:	da1b      	bge.n	8005782 <uECC_vli_modMult+0x106>
            uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
 800574a:	fa0f fc81 	sxth.w	ip, r1
 800574e:	f85a 3cc8 	ldr.w	r3, [sl, #-200]
 8005752:	f853 b02c 	ldr.w	fp, [r3, ip, lsl #2]
 8005756:	ab34      	add	r3, sp, #208	; 0xd0
 8005758:	eb03 0181 	add.w	r1, r3, r1, lsl #2
 800575c:	f851 3c80 	ldr.w	r3, [r1, #-128]
 8005760:	ebc3 030b 	rsb	r3, r3, fp
 8005764:	ebce 0303 	rsb	r3, lr, r3
            if (diff != v[index][i]) {
 8005768:	459b      	cmp	fp, r3
 800576a:	d004      	beq.n	8005776 <uECC_vli_modMult+0xfa>
                borrow = (diff > v[index][i]);
 800576c:	bf34      	ite	cc
 800576e:	f04f 0e01 	movcc.w	lr, #1
 8005772:	f04f 0e00 	movcs.w	lr, #0
            }
            v[1 - index][i] = diff;
 8005776:	f850 1cc8 	ldr.w	r1, [r0, #-200]
 800577a:	3201      	adds	r2, #1
 800577c:	f841 302c 	str.w	r3, [r1, ip, lsl #2]
 8005780:	e7df      	b.n	8005742 <uECC_vli_modMult+0xc6>
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
 8005782:	ebce 0206 	rsb	r2, lr, r6
 8005786:	4256      	negs	r6, r2
        uECC_vli_rshift1(mod_multiple, num_words);
 8005788:	4621      	mov	r1, r4
 800578a:	a814      	add	r0, sp, #80	; 0x50
            if (diff != v[index][i]) {
                borrow = (diff > v[index][i]);
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
 800578c:	4156      	adcs	r6, r2
        uECC_vli_rshift1(mod_multiple, num_words);
 800578e:	f7ff ff67 	bl	8005660 <uECC_vli_rshift1>
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
 8005792:	ab34      	add	r3, sp, #208	; 0xd0
 8005794:	eb03 0384 	add.w	r3, r3, r4, lsl #2
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
 8005798:	4621      	mov	r1, r4
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
 800579a:	f853 2c80 	ldr.w	r2, [r3, #-128]
 800579e:	f859 3c80 	ldr.w	r3, [r9, #-128]
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
 80057a2:	4638      	mov	r0, r7
            }
            v[1 - index][i] = diff;
        }
        index = !(index ^ borrow); /* Swap the index if there was no borrow */
        uECC_vli_rshift1(mod_multiple, num_words);
        mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1);
 80057a4:	ea43 73c2 	orr.w	r3, r3, r2, lsl #31
 80057a8:	3d01      	subs	r5, #1
 80057aa:	f849 3c80 	str.w	r3, [r9, #-128]
 80057ae:	b2ad      	uxth	r5, r5
        uECC_vli_rshift1(mod_multiple + num_words, num_words);
 80057b0:	f7ff ff56 	bl	8005660 <uECC_vli_rshift1>
 80057b4:	e7ba      	b.n	800572c <uECC_vli_modMult+0xb0>
    }
    uECC_vli_set(result, v[index], num_words);
 80057b6:	ab34      	add	r3, sp, #208	; 0xd0
 80057b8:	eb03 0686 	add.w	r6, r3, r6, lsl #2
 80057bc:	4622      	mov	r2, r4
 80057be:	f856 1cc8 	ldr.w	r1, [r6, #-200]
 80057c2:	4640      	mov	r0, r8
 80057c4:	f7ff ff2a 	bl	800561c <uECC_vli_set>
                                   const uECC_word_t *mod,
                                   wordcount_t num_words) {
    uECC_word_t product[2 * uECC_MAX_WORDS];
    uECC_vli_mult(product, left, right, num_words);
    uECC_vli_mmod(result, product, mod, num_words);
}
 80057c8:	b035      	add	sp, #212	; 0xd4
 80057ca:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 80057ce:	bf00      	nop
 80057d0:	8000001f 	.word	0x8000001f

080057d4 <uECC_vli_modMult_fast>:

uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result,
                                        const uECC_word_t *left,
                                        const uECC_word_t *right,
                                        uECC_Curve curve) {
 80057d4:	b530      	push	{r4, r5, lr}
 80057d6:	461c      	mov	r4, r3
 80057d8:	b091      	sub	sp, #68	; 0x44
 80057da:	4605      	mov	r5, r0
    uECC_word_t product[2 * uECC_MAX_WORDS];
    uECC_vli_mult(product, left, right, curve->num_words);
 80057dc:	f993 3000 	ldrsb.w	r3, [r3]
 80057e0:	4668      	mov	r0, sp
 80057e2:	f7ff fe94 	bl	800550e <uECC_vli_mult>
#if (uECC_OPTIMIZATION_LEVEL > 0)
    curve->mmod_fast(result, product);
 80057e6:	f8d4 30b0 	ldr.w	r3, [r4, #176]	; 0xb0
 80057ea:	4669      	mov	r1, sp
 80057ec:	4628      	mov	r0, r5
 80057ee:	4798      	blx	r3
#else
    uECC_vli_mmod(result, product, curve->p, curve->num_words);
#endif
}
 80057f0:	b011      	add	sp, #68	; 0x44
 80057f2:	bd30      	pop	{r4, r5, pc}

080057f4 <uECC_vli_modSquare_fast>:
#endif /* uECC_ENABLE_VLI_API */

uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result,
                                          const uECC_word_t *left,
                                          uECC_Curve curve) {
    uECC_vli_modMult_fast(result, left, left, curve);
 80057f4:	4613      	mov	r3, r2
 80057f6:	460a      	mov	r2, r1
 80057f8:	f7ff bfec 	b.w	80057d4 <uECC_vli_modMult_fast>

080057fc <apply_z>:

/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
static void apply_z(uECC_word_t * X1,
                    uECC_word_t * Y1,
                    const uECC_word_t * const Z,
                    uECC_Curve curve) {
 80057fc:	b5f0      	push	{r4, r5, r6, r7, lr}
 80057fe:	4615      	mov	r5, r2
 8005800:	b089      	sub	sp, #36	; 0x24
 8005802:	461c      	mov	r4, r3
 8005804:	4607      	mov	r7, r0
 8005806:	460e      	mov	r6, r1
    uECC_word_t t1[uECC_MAX_WORDS];

    uECC_vli_modSquare_fast(t1, Z, curve);    /* z^2 */
 8005808:	461a      	mov	r2, r3
 800580a:	4629      	mov	r1, r5
 800580c:	4668      	mov	r0, sp
 800580e:	f7ff fff1 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
 8005812:	4623      	mov	r3, r4
 8005814:	466a      	mov	r2, sp
 8005816:	4639      	mov	r1, r7
 8005818:	4638      	mov	r0, r7
 800581a:	f7ff ffdb 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(t1, t1, Z, curve);  /* z^3 */
 800581e:	4623      	mov	r3, r4
 8005820:	462a      	mov	r2, r5
 8005822:	4669      	mov	r1, sp
 8005824:	4668      	mov	r0, sp
 8005826:	f7ff ffd5 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
 800582a:	4623      	mov	r3, r4
 800582c:	466a      	mov	r2, sp
 800582e:	4631      	mov	r1, r6
 8005830:	4630      	mov	r0, r6
 8005832:	f7ff ffcf 	bl	80057d4 <uECC_vli_modMult_fast>
}
 8005836:	b009      	add	sp, #36	; 0x24
 8005838:	bdf0      	pop	{r4, r5, r6, r7, pc}

0800583a <uECC_vli_nativeToBytes>:

#else

uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
                                         int num_bytes,
                                         const uECC_word_t *native) {
 800583a:	b5f0      	push	{r4, r5, r6, r7, lr}
    wordcount_t i;
    for (i = 0; i < num_bytes; ++i) {
 800583c:	2500      	movs	r5, #0
        unsigned b = num_bytes - 1 - i;
 800583e:	1e4f      	subs	r7, r1, #1

uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes,
                                         int num_bytes,
                                         const uECC_word_t *native) {
    wordcount_t i;
    for (i = 0; i < num_bytes; ++i) {
 8005840:	b26c      	sxtb	r4, r5
 8005842:	428c      	cmp	r4, r1
 8005844:	f105 0501 	add.w	r5, r5, #1
 8005848:	da0a      	bge.n	8005860 <uECC_vli_nativeToBytes+0x26>
        unsigned b = num_bytes - 1 - i;
 800584a:	1b3b      	subs	r3, r7, r4
        bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
 800584c:	089e      	lsrs	r6, r3, #2
 800584e:	f003 0303 	and.w	r3, r3, #3
 8005852:	f852 6026 	ldr.w	r6, [r2, r6, lsl #2]
 8005856:	00db      	lsls	r3, r3, #3
 8005858:	fa26 f303 	lsr.w	r3, r6, r3
 800585c:	5503      	strb	r3, [r0, r4]
 800585e:	e7ef      	b.n	8005840 <uECC_vli_nativeToBytes+0x6>
    }
}
 8005860:	bdf0      	pop	{r4, r5, r6, r7, pc}

08005862 <uECC_vli_bytesToNative>:

uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
                                         const uint8_t *bytes,
                                         int num_bytes) {
 8005862:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
 8005864:	4616      	mov	r6, r2
    wordcount_t i;
    uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
 8005866:	1cd3      	adds	r3, r2, #3
    }
}

uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
                                         const uint8_t *bytes,
                                         int num_bytes) {
 8005868:	460d      	mov	r5, r1
    wordcount_t i;
    uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
 800586a:	2104      	movs	r1, #4
 800586c:	fb93 f1f1 	sdiv	r1, r3, r1
 8005870:	b249      	sxtb	r1, r1
    }
}

uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
                                         const uint8_t *bytes,
                                         int num_bytes) {
 8005872:	4604      	mov	r4, r0
    wordcount_t i;
    uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
    for (i = 0; i < num_bytes; ++i) {
        unsigned b = num_bytes - 1 - i;
 8005874:	1e77      	subs	r7, r6, #1

uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native,
                                         const uint8_t *bytes,
                                         int num_bytes) {
    wordcount_t i;
    uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
 8005876:	f7ff fe8a 	bl	800558e <uECC_vli_clear>
    for (i = 0; i < num_bytes; ++i) {
 800587a:	2200      	movs	r2, #0
 800587c:	b251      	sxtb	r1, r2
 800587e:	428e      	cmp	r6, r1
 8005880:	f102 0201 	add.w	r2, r2, #1
 8005884:	dd0d      	ble.n	80058a2 <uECC_vli_bytesToNative+0x40>
        unsigned b = num_bytes - 1 - i;
 8005886:	1a7b      	subs	r3, r7, r1
        native[b / uECC_WORD_SIZE] |= 
 8005888:	0898      	lsrs	r0, r3, #2
 800588a:	5c69      	ldrb	r1, [r5, r1]
 800588c:	f003 0303 	and.w	r3, r3, #3
 8005890:	00db      	lsls	r3, r3, #3
 8005892:	fa01 f303 	lsl.w	r3, r1, r3
 8005896:	f854 1020 	ldr.w	r1, [r4, r0, lsl #2]
 800589a:	430b      	orrs	r3, r1
 800589c:	f844 3020 	str.w	r3, [r4, r0, lsl #2]
 80058a0:	e7ec      	b.n	800587c <uECC_vli_bytesToNative+0x1a>
            (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
    }
}
 80058a2:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}

080058a4 <uECC_vli_add.isra.0>:
    #define RESUME_SYNTAX ".syntax divided \n\t"
#endif

#if (uECC_OPTIMIZATION_LEVEL >= 2)

uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result,
 80058a4:	b530      	push	{r4, r5, lr}
#endif
    uint32_t carry;
    uint32_t left_word;
    uint32_t right_word;
    
    __asm__ volatile (
 80058a6:	4603      	mov	r3, r0
 80058a8:	2000      	movs	r0, #0
 80058aa:	c910      	ldmia	r1!, {r4}
 80058ac:	ca20      	ldmia	r2!, {r5}
 80058ae:	1964      	adds	r4, r4, r5
 80058b0:	c310      	stmia	r3!, {r4}
 80058b2:	c910      	ldmia	r1!, {r4}
 80058b4:	ca20      	ldmia	r2!, {r5}
 80058b6:	416c      	adcs	r4, r5
 80058b8:	c310      	stmia	r3!, {r4}
 80058ba:	c910      	ldmia	r1!, {r4}
 80058bc:	ca20      	ldmia	r2!, {r5}
 80058be:	416c      	adcs	r4, r5
 80058c0:	c310      	stmia	r3!, {r4}
 80058c2:	c910      	ldmia	r1!, {r4}
 80058c4:	ca20      	ldmia	r2!, {r5}
 80058c6:	416c      	adcs	r4, r5
 80058c8:	c310      	stmia	r3!, {r4}
 80058ca:	c910      	ldmia	r1!, {r4}
 80058cc:	ca20      	ldmia	r2!, {r5}
 80058ce:	416c      	adcs	r4, r5
 80058d0:	c310      	stmia	r3!, {r4}
 80058d2:	c910      	ldmia	r1!, {r4}
 80058d4:	ca20      	ldmia	r2!, {r5}
 80058d6:	416c      	adcs	r4, r5
 80058d8:	c310      	stmia	r3!, {r4}
 80058da:	c910      	ldmia	r1!, {r4}
 80058dc:	ca20      	ldmia	r2!, {r5}
 80058de:	416c      	adcs	r4, r5
 80058e0:	c310      	stmia	r3!, {r4}
 80058e2:	c910      	ldmia	r1!, {r4}
 80058e4:	ca20      	ldmia	r2!, {r5}
 80058e6:	416c      	adcs	r4, r5
 80058e8:	c310      	stmia	r3!, {r4}
 80058ea:	4140      	adcs	r0, r0
          [right] REG_WRITE_LO (right_word)
        :
        : "cc", "memory"
    );
    return carry;
}
 80058ec:	bd30      	pop	{r4, r5, pc}

080058ee <mod_sqrt_default>:

#if uECC_SUPPORT_COMPRESSED_POINT
#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
    uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
 80058ee:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
 80058f2:	b090      	sub	sp, #64	; 0x40
 80058f4:	460e      	mov	r6, r1
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
 80058f6:	2220      	movs	r2, #32
 80058f8:	2100      	movs	r1, #0

#if uECC_SUPPORT_COMPRESSED_POINT
#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
    uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
 80058fa:	4607      	mov	r7, r0
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
 80058fc:	4668      	mov	r0, sp
 80058fe:	f000 fff9 	bl	80068f4 <memset>
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
 8005902:	2220      	movs	r2, #32
#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
    uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
 8005904:	2401      	movs	r4, #1
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
 8005906:	2100      	movs	r1, #0
 8005908:	eb0d 0002 	add.w	r0, sp, r2
#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \
    uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
 800590c:	9400      	str	r4, [sp, #0]
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
 800590e:	f000 fff1 	bl	80068f4 <memset>
    wordcount_t num_words = curve->num_words;
 8005912:	4631      	mov	r1, r6
    
    /* When curve->p == 3 (mod 4), we can compute
       sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
    uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
 8005914:	466a      	mov	r2, sp
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
    wordcount_t num_words = curve->num_words;
 8005916:	f811 5b04 	ldrb.w	r5, [r1], #4
    uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1
/* Compute a = sqrt(a) (mod curve_p). */
static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) {
    bitcount_t i;
    uECC_word_t p1[uECC_MAX_WORDS] = {1};
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
 800591a:	9408      	str	r4, [sp, #32]
    wordcount_t num_words = curve->num_words;
    
    /* When curve->p == 3 (mod 4), we can compute
       sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
    uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
 800591c:	4668      	mov	r0, sp
    for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
 800591e:	b26d      	sxtb	r5, r5
    uECC_word_t l_result[uECC_MAX_WORDS] = {1};
    wordcount_t num_words = curve->num_words;
    
    /* When curve->p == 3 (mod 4), we can compute
       sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */
    uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */
 8005920:	f7ff ffc0 	bl	80058a4 <uECC_vli_add.isra.0>
    for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) {
 8005924:	4629      	mov	r1, r5
 8005926:	4668      	mov	r0, sp
 8005928:	f7ff fe56 	bl	80055d8 <uECC_vli_numBits>
 800592c:	3801      	subs	r0, #1
 800592e:	b284      	uxth	r4, r0
 8005930:	fa0f f884 	sxth.w	r8, r4
 8005934:	f1b8 0f01 	cmp.w	r8, #1
 8005938:	dd12      	ble.n	8005960 <mod_sqrt_default+0x72>
        uECC_vli_modSquare_fast(l_result, l_result, curve);
 800593a:	a908      	add	r1, sp, #32
 800593c:	4608      	mov	r0, r1
 800593e:	4632      	mov	r2, r6
 8005940:	f7ff ff58 	bl	80057f4 <uECC_vli_modSquare_fast>
        if (uECC_vli_testBit(p1, i)) {
 8005944:	4641      	mov	r1, r8
 8005946:	4668      	mov	r0, sp
 8005948:	f7ff fe3c 	bl	80055c4 <uECC_vli_testBit>
 800594c:	b128      	cbz	r0, 800595a <mod_sqrt_default+0x6c>
            uECC_vli_modMult_fast(l_result, l_result, a, curve);
 800594e:	a908      	add	r1, sp, #32
 8005950:	4633      	mov	r3, r6
 8005952:	463a      	mov	r2, r7
 8005954:	4608      	mov	r0, r1
 8005956:	f7ff ff3d 	bl	80057d4 <uECC_vli_modMult_fast>
 800595a:	3c01      	subs	r4, #1
 800595c:	b2a4      	uxth	r4, r4
 800595e:	e7e7      	b.n	8005930 <mod_sqrt_default+0x42>
        }
    }
    uECC_vli_set(a, l_result, num_words);
 8005960:	462a      	mov	r2, r5
 8005962:	a908      	add	r1, sp, #32
 8005964:	4638      	mov	r0, r7
 8005966:	f7ff fe59 	bl	800561c <uECC_vli_set>
}
 800596a:	b010      	add	sp, #64	; 0x40
 800596c:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

08005970 <omega_mult_secp256k1>:
    /* add the 2^32 multiple */
    result[4 + num_words_secp256k1] =
        uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1); 
}
#elif uECC_WORD_SIZE == 4
static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
 8005970:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
 8005972:	460a      	mov	r2, r1
 8005974:	4604      	mov	r4, r0
 8005976:	1f0d      	subs	r5, r1, #4
 8005978:	1f06      	subs	r6, r0, #4
 800597a:	f101 071c 	add.w	r7, r1, #28
    /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
    uint32_t carry = 0;
 800597e:	2300      	movs	r3, #0
    wordcount_t k;
    
    for (k = 0; k < num_words_secp256k1; ++k) {
        uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
 8005980:	f240 3ed1 	movw	lr, #977	; 0x3d1
 8005984:	f855 cf04 	ldr.w	ip, [r5, #4]!
 8005988:	4618      	mov	r0, r3
 800598a:	2100      	movs	r1, #0
 800598c:	fbee 010c 	umlal	r0, r1, lr, ip
static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
    /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
    uint32_t carry = 0;
    wordcount_t k;
    
    for (k = 0; k < num_words_secp256k1; ++k) {
 8005990:	42af      	cmp	r7, r5
        uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
        result[k] = p;
 8005992:	f846 0f04 	str.w	r0, [r6, #4]!
        carry = p >> 32;
 8005996:	460b      	mov	r3, r1
static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) {
    /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */
    uint32_t carry = 0;
    wordcount_t k;
    
    for (k = 0; k < num_words_secp256k1; ++k) {
 8005998:	d1f4      	bne.n	8005984 <omega_mult_secp256k1+0x14>
        uint64_t p = (uint64_t)0x3D1 * right[k] + carry;
        result[k] = p;
        carry = p >> 32;
    }
    result[num_words_secp256k1] = carry;
 800599a:	6221      	str	r1, [r4, #32]
    /* add the 2^32 multiple */
    result[1 + num_words_secp256k1] =
        uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1); 
 800599c:	1d21      	adds	r1, r4, #4
 800599e:	4608      	mov	r0, r1
 80059a0:	f7ff ff80 	bl	80058a4 <uECC_vli_add.isra.0>
        result[k] = p;
        carry = p >> 32;
    }
    result[num_words_secp256k1] = carry;
    /* add the 2^32 multiple */
    result[1 + num_words_secp256k1] =
 80059a4:	6260      	str	r0, [r4, #36]	; 0x24
 80059a6:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}

080059a8 <regularize_k>:
}

static uECC_word_t regularize_k(const uECC_word_t * const k,
                                uECC_word_t *k0,
                                uECC_word_t *k1,
                                uECC_Curve curve) {
 80059a8:	b5f8      	push	{r3, r4, r5, r6, r7, lr}
 80059aa:	460e      	mov	r6, r1
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
 80059ac:	f103 0524 	add.w	r5, r3, #36	; 0x24
}

static uECC_word_t regularize_k(const uECC_word_t * const k,
                                uECC_word_t *k0,
                                uECC_word_t *k1,
                                uECC_Curve curve) {
 80059b0:	4617      	mov	r7, r2
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
 80059b2:	4601      	mov	r1, r0
 80059b4:	462a      	mov	r2, r5
 80059b6:	4630      	mov	r0, r6

static uECC_word_t regularize_k(const uECC_word_t * const k,
                                uECC_word_t *k0,
                                uECC_word_t *k1,
                                uECC_Curve curve) {
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 80059b8:	885c      	ldrh	r4, [r3, #2]
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
 80059ba:	f7ff ff73 	bl	80058a4 <uECC_vli_add.isra.0>
 80059be:	b980      	cbnz	r0, 80059e2 <regularize_k+0x3a>

static uECC_word_t regularize_k(const uECC_word_t * const k,
                                uECC_word_t *k0,
                                uECC_word_t *k1,
                                uECC_Curve curve) {
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 80059c0:	b221      	sxth	r1, r4
 80059c2:	f101 031f 	add.w	r3, r1, #31
 80059c6:	2220      	movs	r2, #32
 80059c8:	fb93 f3f2 	sdiv	r3, r3, r2
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
 80059cc:	b25b      	sxtb	r3, r3
 80059ce:	ebb1 1f43 	cmp.w	r1, r3, lsl #5
 80059d2:	da08      	bge.n	80059e6 <regularize_k+0x3e>
        (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
         uECC_vli_testBit(k0, num_n_bits));
 80059d4:	4630      	mov	r0, r6
 80059d6:	f7ff fdf5 	bl	80055c4 <uECC_vli_testBit>
                                uECC_word_t *k0,
                                uECC_word_t *k1,
                                uECC_Curve curve) {
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    bitcount_t num_n_bits = curve->num_n_bits;
    uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
 80059da:	1c04      	adds	r4, r0, #0
 80059dc:	bf18      	it	ne
 80059de:	2401      	movne	r4, #1
 80059e0:	e002      	b.n	80059e8 <regularize_k+0x40>
 80059e2:	2401      	movs	r4, #1
 80059e4:	e000      	b.n	80059e8 <regularize_k+0x40>
 80059e6:	4604      	mov	r4, r0
        (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
         uECC_vli_testBit(k0, num_n_bits));
    uECC_vli_add(k1, k0, curve->n, num_n_words);
 80059e8:	462a      	mov	r2, r5
 80059ea:	4631      	mov	r1, r6
 80059ec:	4638      	mov	r0, r7
 80059ee:	f7ff ff59 	bl	80058a4 <uECC_vli_add.isra.0>
    return carry;
}
 80059f2:	4620      	mov	r0, r4
 80059f4:	bdf8      	pop	{r3, r4, r5, r6, r7, pc}

080059f6 <uECC_vli_sub.isra.1>:
#define asm_add 1

uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result,
 80059f6:	b530      	push	{r4, r5, lr}
#endif
    uint32_t carry;
    uint32_t left_word;
    uint32_t right_word;
    
    __asm__ volatile (
 80059f8:	2300      	movs	r3, #0
 80059fa:	c910      	ldmia	r1!, {r4}
 80059fc:	ca20      	ldmia	r2!, {r5}
 80059fe:	1b64      	subs	r4, r4, r5
 8005a00:	c010      	stmia	r0!, {r4}
 8005a02:	c910      	ldmia	r1!, {r4}
 8005a04:	ca20      	ldmia	r2!, {r5}
 8005a06:	41ac      	sbcs	r4, r5
 8005a08:	c010      	stmia	r0!, {r4}
 8005a0a:	c910      	ldmia	r1!, {r4}
 8005a0c:	ca20      	ldmia	r2!, {r5}
 8005a0e:	41ac      	sbcs	r4, r5
 8005a10:	c010      	stmia	r0!, {r4}
 8005a12:	c910      	ldmia	r1!, {r4}
 8005a14:	ca20      	ldmia	r2!, {r5}
 8005a16:	41ac      	sbcs	r4, r5
 8005a18:	c010      	stmia	r0!, {r4}
 8005a1a:	c910      	ldmia	r1!, {r4}
 8005a1c:	ca20      	ldmia	r2!, {r5}
 8005a1e:	41ac      	sbcs	r4, r5
 8005a20:	c010      	stmia	r0!, {r4}
 8005a22:	c910      	ldmia	r1!, {r4}
 8005a24:	ca20      	ldmia	r2!, {r5}
 8005a26:	41ac      	sbcs	r4, r5
 8005a28:	c010      	stmia	r0!, {r4}
 8005a2a:	c910      	ldmia	r1!, {r4}
 8005a2c:	ca20      	ldmia	r2!, {r5}
 8005a2e:	41ac      	sbcs	r4, r5
 8005a30:	c010      	stmia	r0!, {r4}
 8005a32:	c910      	ldmia	r1!, {r4}
 8005a34:	ca20      	ldmia	r2!, {r5}
 8005a36:	41ac      	sbcs	r4, r5
 8005a38:	c010      	stmia	r0!, {r4}
 8005a3a:	415b      	adcs	r3, r3
        :
        : "cc", "memory"
    );
    return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting
                      (for some reason...) */
}
 8005a3c:	fab3 f083 	clz	r0, r3
 8005a40:	0940      	lsrs	r0, r0, #5
 8005a42:	bd30      	pop	{r4, r5, pc}

08005a44 <uECC_vli_modAdd>:
   Assumes that left < mod and right < mod, and that result does not overlap mod. */
uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result,
                                  const uECC_word_t *left,
                                  const uECC_word_t *right,
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
 8005a44:	b570      	push	{r4, r5, r6, lr}
 8005a46:	4604      	mov	r4, r0
 8005a48:	461d      	mov	r5, r3
 8005a4a:	f99d 6010 	ldrsb.w	r6, [sp, #16]
    uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
 8005a4e:	f7ff ff29 	bl	80058a4 <uECC_vli_add.isra.0>
    if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
 8005a52:	b930      	cbnz	r0, 8005a62 <uECC_vli_modAdd+0x1e>
 8005a54:	4632      	mov	r2, r6
 8005a56:	4621      	mov	r1, r4
 8005a58:	4628      	mov	r0, r5
 8005a5a:	f7ff fdec 	bl	8005636 <uECC_vli_cmp_unsafe>
 8005a5e:	2801      	cmp	r0, #1
 8005a60:	d006      	beq.n	8005a70 <uECC_vli_modAdd+0x2c>
        /* result > mod (result = mod + remainder), so subtract mod to get remainder. */
        uECC_vli_sub(result, result, mod, num_words);
 8005a62:	462a      	mov	r2, r5
 8005a64:	4621      	mov	r1, r4
 8005a66:	4620      	mov	r0, r4
    }
}
 8005a68:	e8bd 4070 	ldmia.w	sp!, {r4, r5, r6, lr}
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
    uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
    if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
        /* result > mod (result = mod + remainder), so subtract mod to get remainder. */
        uECC_vli_sub(result, result, mod, num_words);
 8005a6c:	f7ff bfc3 	b.w	80059f6 <uECC_vli_sub.isra.1>
 8005a70:	bd70      	pop	{r4, r5, r6, pc}

08005a72 <x_side_secp256k1>:
    uECC_vli_modMult_fast(Y1, Y1, t4, curve);                   /* t2 = B * (A - x3) */
    uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
}

/* Computes result = x^3 + b. result must not overlap x. */
static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) {
 8005a72:	b573      	push	{r0, r1, r4, r5, r6, lr}
 8005a74:	4604      	mov	r4, r0
 8005a76:	4615      	mov	r5, r2
 8005a78:	460e      	mov	r6, r1
    uECC_vli_modSquare_fast(result, x, curve);                                /* r = x^2 */
 8005a7a:	f7ff febb 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(result, result, x, curve);                          /* r = x^3 */
 8005a7e:	462b      	mov	r3, r5
 8005a80:	4632      	mov	r2, r6
 8005a82:	4621      	mov	r1, r4
 8005a84:	4620      	mov	r0, r4
 8005a86:	f7ff fea5 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */
 8005a8a:	2308      	movs	r3, #8
 8005a8c:	9300      	str	r3, [sp, #0]
 8005a8e:	f105 0284 	add.w	r2, r5, #132	; 0x84
 8005a92:	1d2b      	adds	r3, r5, #4
 8005a94:	4621      	mov	r1, r4
 8005a96:	4620      	mov	r0, r4
 8005a98:	f7ff ffd4 	bl	8005a44 <uECC_vli_modAdd>
}
 8005a9c:	b002      	add	sp, #8
 8005a9e:	bd70      	pop	{r4, r5, r6, pc}

08005aa0 <vli_mmod_fast_secp256k1>:

#if (uECC_OPTIMIZATION_LEVEL > 0)
static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right);
static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) {
 8005aa0:	b570      	push	{r4, r5, r6, lr}
 8005aa2:	b090      	sub	sp, #64	; 0x40
 8005aa4:	460e      	mov	r6, r1
 8005aa6:	4604      	mov	r4, r0
    uECC_word_t tmp[2 * num_words_secp256k1];
    uECC_word_t carry;
    
    uECC_vli_clear(tmp, num_words_secp256k1);
 8005aa8:	2108      	movs	r1, #8
 8005aaa:	4668      	mov	r0, sp
 8005aac:	f7ff fd6f 	bl	800558e <uECC_vli_clear>
    uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
 8005ab0:	2108      	movs	r1, #8
 8005ab2:	a808      	add	r0, sp, #32
 8005ab4:	f7ff fd6b 	bl	800558e <uECC_vli_clear>
    
    omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
 8005ab8:	f106 0120 	add.w	r1, r6, #32
 8005abc:	4668      	mov	r0, sp
 8005abe:	f7ff ff57 	bl	8005970 <omega_mult_secp256k1>
    
    carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q       */
 8005ac2:	466a      	mov	r2, sp
 8005ac4:	4631      	mov	r1, r6
 8005ac6:	4620      	mov	r0, r4
 8005ac8:	f7ff feec 	bl	80058a4 <uECC_vli_add.isra.0>
    uECC_vli_clear(product, num_words_secp256k1);
 8005acc:	2108      	movs	r1, #8
    uECC_vli_clear(tmp, num_words_secp256k1);
    uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1);
    
    omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */
    
    carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q       */
 8005ace:	4605      	mov	r5, r0
    uECC_vli_clear(product, num_words_secp256k1);
 8005ad0:	4630      	mov	r0, r6
 8005ad2:	f7ff fd5c 	bl	800558e <uECC_vli_clear>
    omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
 8005ad6:	a908      	add	r1, sp, #32
 8005ad8:	4630      	mov	r0, r6
 8005ada:	f7ff ff49 	bl	8005970 <omega_mult_secp256k1>
    carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */
 8005ade:	4632      	mov	r2, r6
 8005ae0:	4621      	mov	r1, r4
 8005ae2:	4620      	mov	r0, r4
 8005ae4:	f7ff fede 	bl	80058a4 <uECC_vli_add.isra.0>
 8005ae8:	4405      	add	r5, r0
    
    while (carry > 0) {
 8005aea:	b135      	cbz	r5, 8005afa <vli_mmod_fast_secp256k1+0x5a>
        --carry;
        uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
 8005aec:	4a0a      	ldr	r2, [pc, #40]	; (8005b18 <vli_mmod_fast_secp256k1+0x78>)
 8005aee:	4621      	mov	r1, r4
 8005af0:	4620      	mov	r0, r4
    uECC_vli_clear(product, num_words_secp256k1);
    omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */
    carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */
    
    while (carry > 0) {
        --carry;
 8005af2:	3d01      	subs	r5, #1
        uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
 8005af4:	f7ff ff7f 	bl	80059f6 <uECC_vli_sub.isra.1>
 8005af8:	e7f7      	b.n	8005aea <vli_mmod_fast_secp256k1+0x4a>
    }
    if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) {
 8005afa:	2208      	movs	r2, #8
 8005afc:	4906      	ldr	r1, [pc, #24]	; (8005b18 <vli_mmod_fast_secp256k1+0x78>)
 8005afe:	4620      	mov	r0, r4
 8005b00:	f7ff fd99 	bl	8005636 <uECC_vli_cmp_unsafe>
 8005b04:	2800      	cmp	r0, #0
 8005b06:	dd04      	ble.n	8005b12 <vli_mmod_fast_secp256k1+0x72>
        uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1);
 8005b08:	4a03      	ldr	r2, [pc, #12]	; (8005b18 <vli_mmod_fast_secp256k1+0x78>)
 8005b0a:	4621      	mov	r1, r4
 8005b0c:	4620      	mov	r0, r4
 8005b0e:	f7ff ff72 	bl	80059f6 <uECC_vli_sub.isra.1>
    }
}
 8005b12:	b010      	add	sp, #64	; 0x40
 8005b14:	bd70      	pop	{r4, r5, r6, pc}
 8005b16:	bf00      	nop
 8005b18:	080074d8 	.word	0x080074d8

08005b1c <uECC_vli_modSub.isra.2>:
    }
}

/* Computes result = (left - right) % mod.
   Assumes that left < mod and right < mod, and that result does not overlap mod. */
uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result,
 8005b1c:	b538      	push	{r3, r4, r5, lr}
 8005b1e:	4604      	mov	r4, r0
 8005b20:	461d      	mov	r5, r3
                                  const uECC_word_t *left,
                                  const uECC_word_t *right,
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
    uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
 8005b22:	f7ff ff68 	bl	80059f6 <uECC_vli_sub.isra.1>
    if (l_borrow) {
 8005b26:	b130      	cbz	r0, 8005b36 <uECC_vli_modSub.isra.2+0x1a>
        /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
           we can get the correct result from result + mod (with overflow). */
        uECC_vli_add(result, result, mod, num_words);
 8005b28:	462a      	mov	r2, r5
 8005b2a:	4621      	mov	r1, r4
 8005b2c:	4620      	mov	r0, r4
    }
}
 8005b2e:	e8bd 4038 	ldmia.w	sp!, {r3, r4, r5, lr}
                                  wordcount_t num_words) {
    uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
    if (l_borrow) {
        /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
           we can get the correct result from result + mod (with overflow). */
        uECC_vli_add(result, result, mod, num_words);
 8005b32:	f7ff beb7 	b.w	80058a4 <uECC_vli_add.isra.0>
 8005b36:	bd38      	pop	{r3, r4, r5, pc}

08005b38 <XYcZ_add>:
*/
static void XYcZ_add(uECC_word_t * X1,
                     uECC_word_t * Y1,
                     uECC_word_t * X2,
                     uECC_word_t * Y2,
                     uECC_Curve curve) {
 8005b38:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
 8005b3c:	b089      	sub	sp, #36	; 0x24
 8005b3e:	4614      	mov	r4, r2
    /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
    uECC_word_t t5[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
 8005b40:	9d10      	ldr	r5, [sp, #64]	; 0x40
 8005b42:	f815 9b04 	ldrb.w	r9, [r5], #4
*/
static void XYcZ_add(uECC_word_t * X1,
                     uECC_word_t * Y1,
                     uECC_word_t * X2,
                     uECC_word_t * Y2,
                     uECC_Curve curve) {
 8005b46:	461e      	mov	r6, r3
 8005b48:	4607      	mov	r7, r0
 8005b4a:	4688      	mov	r8, r1
    /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
    uECC_word_t t5[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
 8005b4c:	462b      	mov	r3, r5
 8005b4e:	4602      	mov	r2, r0
 8005b50:	4621      	mov	r1, r4
 8005b52:	4668      	mov	r0, sp
 8005b54:	f7ff ffe2 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSquare_fast(t5, t5, curve);                  /* t5 = (x2 - x1)^2 = A */
 8005b58:	9a10      	ldr	r2, [sp, #64]	; 0x40
 8005b5a:	4669      	mov	r1, sp
 8005b5c:	4668      	mov	r0, sp
 8005b5e:	f7ff fe49 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(X1, X1, t5, curve);                /* t1 = x1*A = B */
 8005b62:	9b10      	ldr	r3, [sp, #64]	; 0x40
 8005b64:	466a      	mov	r2, sp
 8005b66:	4639      	mov	r1, r7
 8005b68:	4638      	mov	r0, r7
 8005b6a:	f7ff fe33 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(X2, X2, t5, curve);                /* t3 = x2*A = C */
 8005b6e:	9b10      	ldr	r3, [sp, #64]	; 0x40
 8005b70:	466a      	mov	r2, sp
 8005b72:	4621      	mov	r1, r4
 8005b74:	4620      	mov	r0, r4
 8005b76:	f7ff fe2d 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
 8005b7a:	462b      	mov	r3, r5
 8005b7c:	4642      	mov	r2, r8
 8005b7e:	4631      	mov	r1, r6
 8005b80:	4630      	mov	r0, r6
 8005b82:	f7ff ffcb 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSquare_fast(t5, Y2, curve);                  /* t5 = (y2 - y1)^2 = D */
 8005b86:	9a10      	ldr	r2, [sp, #64]	; 0x40
 8005b88:	4631      	mov	r1, r6
 8005b8a:	4668      	mov	r0, sp
 8005b8c:	f7ff fe32 	bl	80057f4 <uECC_vli_modSquare_fast>
                                                        
    uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
 8005b90:	462b      	mov	r3, r5
 8005b92:	463a      	mov	r2, r7
 8005b94:	4669      	mov	r1, sp
 8005b96:	4668      	mov	r0, sp
 8005b98:	f7ff ffc0 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
 8005b9c:	462b      	mov	r3, r5
 8005b9e:	4622      	mov	r2, r4
 8005ba0:	4669      	mov	r1, sp
 8005ba2:	4668      	mov	r0, sp
 8005ba4:	f7ff ffba 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
 8005ba8:	462b      	mov	r3, r5
 8005baa:	463a      	mov	r2, r7
 8005bac:	4621      	mov	r1, r4
 8005bae:	4620      	mov	r0, r4
 8005bb0:	f7ff ffb4 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(Y1, Y1, X2, curve);                /* t2 = y1*(C - B) */
 8005bb4:	9b10      	ldr	r3, [sp, #64]	; 0x40
 8005bb6:	4622      	mov	r2, r4
 8005bb8:	4641      	mov	r1, r8
 8005bba:	4640      	mov	r0, r8
 8005bbc:	f7ff fe0a 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
 8005bc0:	462b      	mov	r3, r5
 8005bc2:	466a      	mov	r2, sp
 8005bc4:	4639      	mov	r1, r7
 8005bc6:	4620      	mov	r0, r4
 8005bc8:	f7ff ffa8 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(Y2, Y2, X2, curve);                /* t4 = (y2 - y1)*(B - x3) */
 8005bcc:	9b10      	ldr	r3, [sp, #64]	; 0x40
 8005bce:	4622      	mov	r2, r4
 8005bd0:	4631      	mov	r1, r6
 8005bd2:	4630      	mov	r0, r6
 8005bd4:	f7ff fdfe 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
 8005bd8:	462b      	mov	r3, r5
 8005bda:	4642      	mov	r2, r8
 8005bdc:	4631      	mov	r1, r6
 8005bde:	4630      	mov	r0, r6
 8005be0:	f7ff ff9c 	bl	8005b1c <uECC_vli_modSub.isra.2>
    
    uECC_vli_set(X2, t5, num_words);
 8005be4:	fa4f f289 	sxtb.w	r2, r9
 8005be8:	4669      	mov	r1, sp
 8005bea:	4620      	mov	r0, r4
 8005bec:	f7ff fd16 	bl	800561c <uECC_vli_set>
}
 8005bf0:	b009      	add	sp, #36	; 0x24
 8005bf2:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}

08005bf6 <XYcZ_addC>:
*/
static void XYcZ_addC(uECC_word_t * X1,
                      uECC_word_t * Y1,
                      uECC_word_t * X2,
                      uECC_word_t * Y2,
                      uECC_Curve curve) {
 8005bf6:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
 8005bfa:	b09b      	sub	sp, #108	; 0x6c
 8005bfc:	4615      	mov	r5, r2
    /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
    uECC_word_t t5[uECC_MAX_WORDS];
    uECC_word_t t6[uECC_MAX_WORDS];
    uECC_word_t t7[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
 8005bfe:	9c22      	ldr	r4, [sp, #136]	; 0x88
 8005c00:	f814 9b04 	ldrb.w	r9, [r4], #4
*/
static void XYcZ_addC(uECC_word_t * X1,
                      uECC_word_t * Y1,
                      uECC_word_t * X2,
                      uECC_word_t * Y2,
                      uECC_Curve curve) {
 8005c04:	461f      	mov	r7, r3
 8005c06:	4606      	mov	r6, r0
 8005c08:	4688      	mov	r8, r1
    uECC_word_t t5[uECC_MAX_WORDS];
    uECC_word_t t6[uECC_MAX_WORDS];
    uECC_word_t t7[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
 8005c0a:	4623      	mov	r3, r4
 8005c0c:	4602      	mov	r2, r0
 8005c0e:	4629      	mov	r1, r5
 8005c10:	a802      	add	r0, sp, #8
 8005c12:	f7ff ff83 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSquare_fast(t5, t5, curve);                  /* t5 = (x2 - x1)^2 = A */
 8005c16:	a902      	add	r1, sp, #8
 8005c18:	9a22      	ldr	r2, [sp, #136]	; 0x88
 8005c1a:	4608      	mov	r0, r1
 8005c1c:	f7ff fdea 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(X1, X1, t5, curve);                /* t1 = x1*A = B */
 8005c20:	9b22      	ldr	r3, [sp, #136]	; 0x88
 8005c22:	aa02      	add	r2, sp, #8
 8005c24:	4631      	mov	r1, r6
 8005c26:	4630      	mov	r0, r6
 8005c28:	f7ff fdd4 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(X2, X2, t5, curve);                /* t3 = x2*A = C */
    uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
 8005c2c:	fa4f f989 	sxtb.w	r9, r9
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
    uECC_vli_modSquare_fast(t5, t5, curve);                  /* t5 = (x2 - x1)^2 = A */
    uECC_vli_modMult_fast(X1, X1, t5, curve);                /* t1 = x1*A = B */
    uECC_vli_modMult_fast(X2, X2, t5, curve);                /* t3 = x2*A = C */
 8005c30:	9b22      	ldr	r3, [sp, #136]	; 0x88
 8005c32:	aa02      	add	r2, sp, #8
 8005c34:	4629      	mov	r1, r5
 8005c36:	4628      	mov	r0, r5
 8005c38:	f7ff fdcc 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
 8005c3c:	4623      	mov	r3, r4
 8005c3e:	4642      	mov	r2, r8
 8005c40:	4639      	mov	r1, r7
 8005c42:	a802      	add	r0, sp, #8
 8005c44:	f8cd 9000 	str.w	r9, [sp]
 8005c48:	f7ff fefc 	bl	8005a44 <uECC_vli_modAdd>
    uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
 8005c4c:	4623      	mov	r3, r4
 8005c4e:	4642      	mov	r2, r8
 8005c50:	4639      	mov	r1, r7
 8005c52:	4638      	mov	r0, r7
 8005c54:	f7ff ff62 	bl	8005b1c <uECC_vli_modSub.isra.2>
                                                        
    uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
 8005c58:	4623      	mov	r3, r4
 8005c5a:	4632      	mov	r2, r6
 8005c5c:	4629      	mov	r1, r5
 8005c5e:	a80a      	add	r0, sp, #40	; 0x28
 8005c60:	f7ff ff5c 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(Y1, Y1, t6, curve);                /* t2 = y1 * (C - B) = E */
 8005c64:	9b22      	ldr	r3, [sp, #136]	; 0x88
 8005c66:	aa0a      	add	r2, sp, #40	; 0x28
 8005c68:	4641      	mov	r1, r8
 8005c6a:	4640      	mov	r0, r8
 8005c6c:	f7ff fdb2 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
 8005c70:	4623      	mov	r3, r4
 8005c72:	462a      	mov	r2, r5
 8005c74:	4631      	mov	r1, r6
 8005c76:	a80a      	add	r0, sp, #40	; 0x28
 8005c78:	f8cd 9000 	str.w	r9, [sp]
 8005c7c:	f7ff fee2 	bl	8005a44 <uECC_vli_modAdd>
    uECC_vli_modSquare_fast(X2, Y2, curve);                  /* t3 = (y2 - y1)^2 = D */
 8005c80:	9a22      	ldr	r2, [sp, #136]	; 0x88
 8005c82:	4639      	mov	r1, r7
 8005c84:	4628      	mov	r0, r5
 8005c86:	f7ff fdb5 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
 8005c8a:	4623      	mov	r3, r4
 8005c8c:	aa0a      	add	r2, sp, #40	; 0x28
 8005c8e:	4629      	mov	r1, r5
 8005c90:	4628      	mov	r0, r5
 8005c92:	f7ff ff43 	bl	8005b1c <uECC_vli_modSub.isra.2>
                                                        
    uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
 8005c96:	4623      	mov	r3, r4
 8005c98:	462a      	mov	r2, r5
 8005c9a:	4631      	mov	r1, r6
 8005c9c:	a812      	add	r0, sp, #72	; 0x48
 8005c9e:	f7ff ff3d 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(Y2, Y2, t7, curve);                /* t4 = (y2 - y1)*(B - x3) */
 8005ca2:	9b22      	ldr	r3, [sp, #136]	; 0x88
 8005ca4:	aa12      	add	r2, sp, #72	; 0x48
 8005ca6:	4639      	mov	r1, r7
 8005ca8:	4638      	mov	r0, r7
 8005caa:	f7ff fd93 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */
 8005cae:	4623      	mov	r3, r4
 8005cb0:	4642      	mov	r2, r8
 8005cb2:	4639      	mov	r1, r7
 8005cb4:	4638      	mov	r0, r7
 8005cb6:	f7ff ff31 	bl	8005b1c <uECC_vli_modSub.isra.2>
                                                        
    uECC_vli_modSquare_fast(t7, t5, curve);                  /* t7 = (y2 + y1)^2 = F */
 8005cba:	9a22      	ldr	r2, [sp, #136]	; 0x88
 8005cbc:	a902      	add	r1, sp, #8
 8005cbe:	a812      	add	r0, sp, #72	; 0x48
 8005cc0:	f7ff fd98 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
 8005cc4:	a912      	add	r1, sp, #72	; 0x48
 8005cc6:	4623      	mov	r3, r4
 8005cc8:	aa0a      	add	r2, sp, #40	; 0x28
 8005cca:	4608      	mov	r0, r1
 8005ccc:	f7ff ff26 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
 8005cd0:	4623      	mov	r3, r4
 8005cd2:	4632      	mov	r2, r6
 8005cd4:	a912      	add	r1, sp, #72	; 0x48
 8005cd6:	a80a      	add	r0, sp, #40	; 0x28
 8005cd8:	f7ff ff20 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(t6, t6, t5, curve);                /* t6 = (y2+y1)*(x3' - B) */
 8005cdc:	a90a      	add	r1, sp, #40	; 0x28
 8005cde:	9b22      	ldr	r3, [sp, #136]	; 0x88
 8005ce0:	aa02      	add	r2, sp, #8
 8005ce2:	4608      	mov	r0, r1
 8005ce4:	f7ff fd76 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */
 8005ce8:	4623      	mov	r3, r4
 8005cea:	4642      	mov	r2, r8
 8005cec:	a90a      	add	r1, sp, #40	; 0x28
 8005cee:	4640      	mov	r0, r8
 8005cf0:	f7ff ff14 	bl	8005b1c <uECC_vli_modSub.isra.2>
    
    uECC_vli_set(X1, t7, num_words);
 8005cf4:	464a      	mov	r2, r9
 8005cf6:	a912      	add	r1, sp, #72	; 0x48
 8005cf8:	4630      	mov	r0, r6
 8005cfa:	f7ff fc8f 	bl	800561c <uECC_vli_set>
}
 8005cfe:	b01b      	add	sp, #108	; 0x6c
 8005d00:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}

08005d04 <vli_modInv_update>:
#define EVEN(vli) (!(vli[0] & 1))
static void vli_modInv_update(uECC_word_t *uv,
                              const uECC_word_t *mod,
                              wordcount_t num_words) {
    uECC_word_t carry = 0;
    if (!EVEN(uv)) {
 8005d04:	6803      	ldr	r3, [r0, #0]
#endif /* uECC_SQUARE_FUNC */

#define EVEN(vli) (!(vli[0] & 1))
static void vli_modInv_update(uECC_word_t *uv,
                              const uECC_word_t *mod,
                              wordcount_t num_words) {
 8005d06:	b570      	push	{r4, r5, r6, lr}
    uECC_word_t carry = 0;
    if (!EVEN(uv)) {
 8005d08:	f013 0501 	ands.w	r5, r3, #1
#endif /* uECC_SQUARE_FUNC */

#define EVEN(vli) (!(vli[0] & 1))
static void vli_modInv_update(uECC_word_t *uv,
                              const uECC_word_t *mod,
                              wordcount_t num_words) {
 8005d0c:	4606      	mov	r6, r0
 8005d0e:	4614      	mov	r4, r2
    uECC_word_t carry = 0;
    if (!EVEN(uv)) {
 8005d10:	d004      	beq.n	8005d1c <vli_modInv_update+0x18>
        carry = uECC_vli_add(uv, uv, mod, num_words);
 8005d12:	460a      	mov	r2, r1
 8005d14:	4601      	mov	r1, r0
 8005d16:	f7ff fdc5 	bl	80058a4 <uECC_vli_add.isra.0>
 8005d1a:	4605      	mov	r5, r0
    }
    uECC_vli_rshift1(uv, num_words);
 8005d1c:	4621      	mov	r1, r4
 8005d1e:	4630      	mov	r0, r6
 8005d20:	f7ff fc9e 	bl	8005660 <uECC_vli_rshift1>
    if (carry) {
 8005d24:	b145      	cbz	r5, 8005d38 <vli_modInv_update+0x34>
        uv[num_words - 1] |= HIGH_BIT_SET;
 8005d26:	f104 4280 	add.w	r2, r4, #1073741824	; 0x40000000
 8005d2a:	3a01      	subs	r2, #1
 8005d2c:	f856 3022 	ldr.w	r3, [r6, r2, lsl #2]
 8005d30:	f043 4300 	orr.w	r3, r3, #2147483648	; 0x80000000
 8005d34:	f846 3022 	str.w	r3, [r6, r2, lsl #2]
 8005d38:	bd70      	pop	{r4, r5, r6, pc}

08005d3a <uECC_vli_modInv>:
/* Computes result = (1 / input) % mod. All VLIs are the same size.
   See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */
uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result,
                                  const uECC_word_t *input,
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
 8005d3a:	b5f0      	push	{r4, r5, r6, r7, lr}
 8005d3c:	460f      	mov	r7, r1
 8005d3e:	b0a1      	sub	sp, #132	; 0x84
 8005d40:	4606      	mov	r6, r0
    uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
    cmpresult_t cmpResult;
    
    if (uECC_vli_isZero(input, num_words)) {
 8005d42:	4619      	mov	r1, r3
 8005d44:	4638      	mov	r0, r7
/* Computes result = (1 / input) % mod. All VLIs are the same size.
   See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */
uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result,
                                  const uECC_word_t *input,
                                  const uECC_word_t *mod,
                                  wordcount_t num_words) {
 8005d46:	4615      	mov	r5, r2
 8005d48:	461c      	mov	r4, r3
    uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
    cmpresult_t cmpResult;
    
    if (uECC_vli_isZero(input, num_words)) {
 8005d4a:	f7ff fc2c 	bl	80055a6 <uECC_vli_isZero>
 8005d4e:	b120      	cbz	r0, 8005d5a <uECC_vli_modInv+0x20>
        uECC_vli_clear(result, num_words);
 8005d50:	4621      	mov	r1, r4
 8005d52:	4630      	mov	r0, r6
 8005d54:	f7ff fc1b 	bl	800558e <uECC_vli_clear>
 8005d58:	e06f      	b.n	8005e3a <uECC_vli_modInv+0x100>
        return;
    }

    uECC_vli_set(a, input, num_words);
 8005d5a:	4622      	mov	r2, r4
 8005d5c:	4639      	mov	r1, r7
 8005d5e:	4668      	mov	r0, sp
 8005d60:	f7ff fc5c 	bl	800561c <uECC_vli_set>
    uECC_vli_set(b, mod, num_words);
 8005d64:	4622      	mov	r2, r4
 8005d66:	4629      	mov	r1, r5
 8005d68:	a808      	add	r0, sp, #32
 8005d6a:	f7ff fc57 	bl	800561c <uECC_vli_set>
    uECC_vli_clear(u, num_words);
 8005d6e:	4621      	mov	r1, r4
 8005d70:	a810      	add	r0, sp, #64	; 0x40
 8005d72:	f7ff fc0c 	bl	800558e <uECC_vli_clear>
    u[0] = 1;
 8005d76:	2301      	movs	r3, #1
    uECC_vli_clear(v, num_words);
 8005d78:	4621      	mov	r1, r4
 8005d7a:	a818      	add	r0, sp, #96	; 0x60
    }

    uECC_vli_set(a, input, num_words);
    uECC_vli_set(b, mod, num_words);
    uECC_vli_clear(u, num_words);
    u[0] = 1;
 8005d7c:	9310      	str	r3, [sp, #64]	; 0x40
    uECC_vli_clear(v, num_words);
 8005d7e:	f7ff fc06 	bl	800558e <uECC_vli_clear>
    while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
 8005d82:	4622      	mov	r2, r4
 8005d84:	a908      	add	r1, sp, #32
 8005d86:	4668      	mov	r0, sp
 8005d88:	f7ff fc55 	bl	8005636 <uECC_vli_cmp_unsafe>
 8005d8c:	2800      	cmp	r0, #0
 8005d8e:	d04f      	beq.n	8005e30 <uECC_vli_modInv+0xf6>
        if (EVEN(a)) {
 8005d90:	9b00      	ldr	r3, [sp, #0]
 8005d92:	07da      	lsls	r2, r3, #31
 8005d94:	d404      	bmi.n	8005da0 <uECC_vli_modInv+0x66>
            uECC_vli_rshift1(a, num_words);
 8005d96:	4621      	mov	r1, r4
 8005d98:	4668      	mov	r0, sp
 8005d9a:	f7ff fc61 	bl	8005660 <uECC_vli_rshift1>
 8005d9e:	e023      	b.n	8005de8 <uECC_vli_modInv+0xae>
            vli_modInv_update(u, mod, num_words);
        } else if (EVEN(b)) {
 8005da0:	9b08      	ldr	r3, [sp, #32]
 8005da2:	07db      	lsls	r3, r3, #31
 8005da4:	d404      	bmi.n	8005db0 <uECC_vli_modInv+0x76>
            uECC_vli_rshift1(b, num_words);
 8005da6:	4621      	mov	r1, r4
 8005da8:	a808      	add	r0, sp, #32
 8005daa:	f7ff fc59 	bl	8005660 <uECC_vli_rshift1>
 8005dae:	e039      	b.n	8005e24 <uECC_vli_modInv+0xea>
            vli_modInv_update(v, mod, num_words);
        } else if (cmpResult > 0) {
 8005db0:	2800      	cmp	r0, #0
 8005db2:	dd1d      	ble.n	8005df0 <uECC_vli_modInv+0xb6>
            uECC_vli_sub(a, a, b, num_words);
 8005db4:	aa08      	add	r2, sp, #32
 8005db6:	4669      	mov	r1, sp
 8005db8:	4668      	mov	r0, sp
 8005dba:	f7ff fe1c 	bl	80059f6 <uECC_vli_sub.isra.1>
            uECC_vli_rshift1(a, num_words);
 8005dbe:	4621      	mov	r1, r4
 8005dc0:	4668      	mov	r0, sp
 8005dc2:	f7ff fc4d 	bl	8005660 <uECC_vli_rshift1>
            if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
 8005dc6:	4622      	mov	r2, r4
 8005dc8:	a918      	add	r1, sp, #96	; 0x60
 8005dca:	a810      	add	r0, sp, #64	; 0x40
 8005dcc:	f7ff fc33 	bl	8005636 <uECC_vli_cmp_unsafe>
 8005dd0:	2800      	cmp	r0, #0
 8005dd2:	da04      	bge.n	8005dde <uECC_vli_modInv+0xa4>
                uECC_vli_add(u, u, mod, num_words);
 8005dd4:	a910      	add	r1, sp, #64	; 0x40
 8005dd6:	462a      	mov	r2, r5
 8005dd8:	4608      	mov	r0, r1
 8005dda:	f7ff fd63 	bl	80058a4 <uECC_vli_add.isra.0>
            }
            uECC_vli_sub(u, u, v, num_words);
 8005dde:	a910      	add	r1, sp, #64	; 0x40
 8005de0:	aa18      	add	r2, sp, #96	; 0x60
 8005de2:	4608      	mov	r0, r1
 8005de4:	f7ff fe07 	bl	80059f6 <uECC_vli_sub.isra.1>
            vli_modInv_update(u, mod, num_words);
 8005de8:	4622      	mov	r2, r4
 8005dea:	4629      	mov	r1, r5
 8005dec:	a810      	add	r0, sp, #64	; 0x40
 8005dee:	e01c      	b.n	8005e2a <uECC_vli_modInv+0xf0>
        } else {
            uECC_vli_sub(b, b, a, num_words);
 8005df0:	a908      	add	r1, sp, #32
 8005df2:	466a      	mov	r2, sp
 8005df4:	4608      	mov	r0, r1
 8005df6:	f7ff fdfe 	bl	80059f6 <uECC_vli_sub.isra.1>
            uECC_vli_rshift1(b, num_words);
 8005dfa:	4621      	mov	r1, r4
 8005dfc:	a808      	add	r0, sp, #32
 8005dfe:	f7ff fc2f 	bl	8005660 <uECC_vli_rshift1>
            if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
 8005e02:	4622      	mov	r2, r4
 8005e04:	a910      	add	r1, sp, #64	; 0x40
 8005e06:	a818      	add	r0, sp, #96	; 0x60
 8005e08:	f7ff fc15 	bl	8005636 <uECC_vli_cmp_unsafe>
 8005e0c:	2800      	cmp	r0, #0
 8005e0e:	da04      	bge.n	8005e1a <uECC_vli_modInv+0xe0>
                uECC_vli_add(v, v, mod, num_words);
 8005e10:	a918      	add	r1, sp, #96	; 0x60
 8005e12:	462a      	mov	r2, r5
 8005e14:	4608      	mov	r0, r1
 8005e16:	f7ff fd45 	bl	80058a4 <uECC_vli_add.isra.0>
            }
            uECC_vli_sub(v, v, u, num_words);
 8005e1a:	a918      	add	r1, sp, #96	; 0x60
 8005e1c:	aa10      	add	r2, sp, #64	; 0x40
 8005e1e:	4608      	mov	r0, r1
 8005e20:	f7ff fde9 	bl	80059f6 <uECC_vli_sub.isra.1>
            vli_modInv_update(v, mod, num_words);
 8005e24:	4622      	mov	r2, r4
 8005e26:	4629      	mov	r1, r5
 8005e28:	a818      	add	r0, sp, #96	; 0x60
 8005e2a:	f7ff ff6b 	bl	8005d04 <vli_modInv_update>
 8005e2e:	e7a8      	b.n	8005d82 <uECC_vli_modInv+0x48>
        }
    }
    uECC_vli_set(result, u, num_words);
 8005e30:	4622      	mov	r2, r4
 8005e32:	a910      	add	r1, sp, #64	; 0x40
 8005e34:	4630      	mov	r0, r6
 8005e36:	f7ff fbf1 	bl	800561c <uECC_vli_set>
}
 8005e3a:	b021      	add	sp, #132	; 0x84
 8005e3c:	bdf0      	pop	{r4, r5, r6, r7, pc}

08005e3e <EccPoint_mult>:
static void EccPoint_mult(uECC_word_t * result,
                          const uECC_word_t * point,
                          const uECC_word_t * scalar,
                          const uECC_word_t * initial_Z,
                          bitcount_t num_bits,
                          uECC_Curve curve) {
 8005e3e:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
 8005e42:	b0b1      	sub	sp, #196	; 0xc4
 8005e44:	461e      	mov	r6, r3
 8005e46:	9c3b      	ldr	r4, [sp, #236]	; 0xec
 8005e48:	9004      	str	r0, [sp, #16]
    uECC_word_t z[uECC_MAX_WORDS];
    bitcount_t i;
    uECC_word_t nb;
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_set(Rx[1], point, num_words);
 8005e4a:	f994 8000 	ldrsb.w	r8, [r4]
static void EccPoint_mult(uECC_word_t * result,
                          const uECC_word_t * point,
                          const uECC_word_t * scalar,
                          const uECC_word_t * initial_Z,
                          bitcount_t num_bits,
                          uECC_Curve curve) {
 8005e4e:	9206      	str	r2, [sp, #24]
    uECC_word_t z[uECC_MAX_WORDS];
    bitcount_t i;
    uECC_word_t nb;
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_set(Rx[1], point, num_words);
 8005e50:	a818      	add	r0, sp, #96	; 0x60
 8005e52:	4642      	mov	r2, r8
static void EccPoint_mult(uECC_word_t * result,
                          const uECC_word_t * point,
                          const uECC_word_t * scalar,
                          const uECC_word_t * initial_Z,
                          bitcount_t num_bits,
                          uECC_Curve curve) {
 8005e54:	9105      	str	r1, [sp, #20]
    uECC_word_t z[uECC_MAX_WORDS];
    bitcount_t i;
    uECC_word_t nb;
    wordcount_t num_words = curve->num_words;
    
    uECC_vli_set(Rx[1], point, num_words);
 8005e56:	f7ff fbe1 	bl	800561c <uECC_vli_set>
    uECC_vli_set(Ry[1], point + num_words, num_words);
 8005e5a:	ea4f 0388 	mov.w	r3, r8, lsl #2
 8005e5e:	9302      	str	r3, [sp, #8]
 8005e60:	9a02      	ldr	r2, [sp, #8]
 8005e62:	9b05      	ldr	r3, [sp, #20]
 8005e64:	4413      	add	r3, r2
 8005e66:	4619      	mov	r1, r3
 8005e68:	4642      	mov	r2, r8
 8005e6a:	a828      	add	r0, sp, #160	; 0xa0
 8005e6c:	9303      	str	r3, [sp, #12]
 8005e6e:	f7ff fbd5 	bl	800561c <uECC_vli_set>
 8005e72:	f994 5000 	ldrsb.w	r5, [r4]
                                uECC_word_t * Y2,
                                const uECC_word_t * const initial_Z,
                                uECC_Curve curve) {
    uECC_word_t z[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    if (initial_Z) {
 8005e76:	b12e      	cbz	r6, 8005e84 <EccPoint_mult+0x46>
        uECC_vli_set(z, initial_Z, num_words);
 8005e78:	462a      	mov	r2, r5
 8005e7a:	4631      	mov	r1, r6
 8005e7c:	a808      	add	r0, sp, #32
 8005e7e:	f7ff fbcd 	bl	800561c <uECC_vli_set>
 8005e82:	e005      	b.n	8005e90 <EccPoint_mult+0x52>
    } else {
        uECC_vli_clear(z, num_words);
 8005e84:	4629      	mov	r1, r5
 8005e86:	a808      	add	r0, sp, #32
 8005e88:	f7ff fb81 	bl	800558e <uECC_vli_clear>
        z[0] = 1;
 8005e8c:	2301      	movs	r3, #1
 8005e8e:	9308      	str	r3, [sp, #32]
    }

    uECC_vli_set(X2, X1, num_words);
 8005e90:	af10      	add	r7, sp, #64	; 0x40
 8005e92:	462a      	mov	r2, r5
 8005e94:	a918      	add	r1, sp, #96	; 0x60
 8005e96:	4638      	mov	r0, r7
    uECC_vli_set(Y2, Y1, num_words);
 8005e98:	f10d 0980 	add.w	r9, sp, #128	; 0x80
    } else {
        uECC_vli_clear(z, num_words);
        z[0] = 1;
    }

    uECC_vli_set(X2, X1, num_words);
 8005e9c:	f7ff fbbe 	bl	800561c <uECC_vli_set>
    uECC_vli_set(Y2, Y1, num_words);
 8005ea0:	462a      	mov	r2, r5
 8005ea2:	a928      	add	r1, sp, #160	; 0xa0
 8005ea4:	4648      	mov	r0, r9
 8005ea6:	f7ff fbb9 	bl	800561c <uECC_vli_set>

    apply_z(X1, Y1, z, curve);
 8005eaa:	4623      	mov	r3, r4
 8005eac:	aa08      	add	r2, sp, #32
 8005eae:	a928      	add	r1, sp, #160	; 0xa0
 8005eb0:	a818      	add	r0, sp, #96	; 0x60
 8005eb2:	f7ff fca3 	bl	80057fc <apply_z>
    curve->double_jacobian(X1, Y1, z, curve);
 8005eb6:	4623      	mov	r3, r4
 8005eb8:	aa08      	add	r2, sp, #32
 8005eba:	a928      	add	r1, sp, #160	; 0xa0
 8005ebc:	a818      	add	r0, sp, #96	; 0x60
 8005ebe:	f8d4 50a4 	ldr.w	r5, [r4, #164]	; 0xa4
 8005ec2:	47a8      	blx	r5
    apply_z(X2, Y2, z, curve);
 8005ec4:	4623      	mov	r3, r4
 8005ec6:	aa08      	add	r2, sp, #32
 8005ec8:	4649      	mov	r1, r9
 8005eca:	4638      	mov	r0, r7
 8005ecc:	f7ff fc96 	bl	80057fc <apply_z>
    uECC_vli_set(Rx[1], point, num_words);
    uECC_vli_set(Ry[1], point + num_words, num_words);

    XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);

    for (i = num_bits - 2; i > 0; --i) {
 8005ed0:	f9bd 60e8 	ldrsh.w	r6, [sp, #232]	; 0xe8
        nb = !uECC_vli_testBit(scalar, i);
        XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
 8005ed4:	9707      	str	r7, [sp, #28]
    uECC_vli_set(Rx[1], point, num_words);
    uECC_vli_set(Ry[1], point + num_words, num_words);

    XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);

    for (i = num_bits - 2; i > 0; --i) {
 8005ed6:	3e02      	subs	r6, #2
 8005ed8:	b2b6      	uxth	r6, r6
 8005eda:	b231      	sxth	r1, r6
 8005edc:	2900      	cmp	r1, #0
 8005ede:	dd22      	ble.n	8005f26 <EccPoint_mult+0xe8>
        nb = !uECC_vli_testBit(scalar, i);
 8005ee0:	9806      	ldr	r0, [sp, #24]
 8005ee2:	f7ff fb6f 	bl	80055c4 <uECC_vli_testBit>
 8005ee6:	fab0 f080 	clz	r0, r0
 8005eea:	0940      	lsrs	r0, r0, #5
        XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
 8005eec:	9b07      	ldr	r3, [sp, #28]
 8005eee:	9400      	str	r4, [sp, #0]
 8005ef0:	f1c0 0701 	rsb	r7, r0, #1
 8005ef4:	017f      	lsls	r7, r7, #5
 8005ef6:	0140      	lsls	r0, r0, #5
 8005ef8:	eb03 0b07 	add.w	fp, r3, r7
 8005efc:	eb03 0a00 	add.w	sl, r3, r0
 8005f00:	eb09 0500 	add.w	r5, r9, r0
 8005f04:	444f      	add	r7, r9
 8005f06:	462b      	mov	r3, r5
 8005f08:	4652      	mov	r2, sl
 8005f0a:	4639      	mov	r1, r7
 8005f0c:	4658      	mov	r0, fp
 8005f0e:	f7ff fe72 	bl	8005bf6 <XYcZ_addC>
 8005f12:	3e01      	subs	r6, #1
        XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
 8005f14:	9400      	str	r4, [sp, #0]
 8005f16:	463b      	mov	r3, r7
 8005f18:	465a      	mov	r2, fp
 8005f1a:	4629      	mov	r1, r5
 8005f1c:	4650      	mov	r0, sl
 8005f1e:	f7ff fe0b 	bl	8005b38 <XYcZ_add>
 8005f22:	b2b6      	uxth	r6, r6
 8005f24:	e7d9      	b.n	8005eda <EccPoint_mult+0x9c>
 8005f26:	9b06      	ldr	r3, [sp, #24]
 8005f28:	681d      	ldr	r5, [r3, #0]
    }

    nb = !uECC_vli_testBit(scalar, 0);
    XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
 8005f2a:	9400      	str	r4, [sp, #0]
 8005f2c:	f005 0501 	and.w	r5, r5, #1
 8005f30:	f085 0501 	eor.w	r5, r5, #1
 8005f34:	f1c5 0601 	rsb	r6, r5, #1
 8005f38:	ab10      	add	r3, sp, #64	; 0x40
 8005f3a:	0176      	lsls	r6, r6, #5
 8005f3c:	199f      	adds	r7, r3, r6
 8005f3e:	ab20      	add	r3, sp, #128	; 0x80
 8005f40:	441e      	add	r6, r3
 8005f42:	016d      	lsls	r5, r5, #5
 8005f44:	ab10      	add	r3, sp, #64	; 0x40
 8005f46:	eb03 0905 	add.w	r9, r3, r5
 8005f4a:	ab20      	add	r3, sp, #128	; 0x80
 8005f4c:	441d      	add	r5, r3
    
    /* Find final 1/Z value. */
    uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
 8005f4e:	f104 0a04 	add.w	sl, r4, #4
        XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
        XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
    }

    nb = !uECC_vli_testBit(scalar, 0);
    XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
 8005f52:	462b      	mov	r3, r5
 8005f54:	464a      	mov	r2, r9
 8005f56:	4631      	mov	r1, r6
 8005f58:	4638      	mov	r0, r7
 8005f5a:	f7ff fe4c 	bl	8005bf6 <XYcZ_addC>
    
    /* Find final 1/Z value. */
    uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
 8005f5e:	4653      	mov	r3, sl
 8005f60:	aa10      	add	r2, sp, #64	; 0x40
 8005f62:	a918      	add	r1, sp, #96	; 0x60
 8005f64:	a808      	add	r0, sp, #32
 8005f66:	f7ff fdd9 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve);               /* Yb * (X1 - X0) */
 8005f6a:	a908      	add	r1, sp, #32
 8005f6c:	4623      	mov	r3, r4
 8005f6e:	4632      	mov	r2, r6
 8005f70:	4608      	mov	r0, r1
 8005f72:	f7ff fc2f 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(z, z, point, curve);                    /* xP * Yb * (X1 - X0) */
 8005f76:	a908      	add	r1, sp, #32
 8005f78:	4623      	mov	r3, r4
 8005f7a:	9a05      	ldr	r2, [sp, #20]
 8005f7c:	4608      	mov	r0, r1
 8005f7e:	f7ff fc29 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modInv(z, z, curve->p, num_words);            /* 1 / (xP * Yb * (X1 - X0)) */
 8005f82:	a908      	add	r1, sp, #32
 8005f84:	4643      	mov	r3, r8
 8005f86:	4652      	mov	r2, sl
 8005f88:	4608      	mov	r0, r1
 8005f8a:	f7ff fed6 	bl	8005d3a <uECC_vli_modInv>
    /* yP / (xP * Yb * (X1 - X0)) */
    uECC_vli_modMult_fast(z, z, point + num_words, curve); 
 8005f8e:	a908      	add	r1, sp, #32
 8005f90:	4623      	mov	r3, r4
 8005f92:	9a03      	ldr	r2, [sp, #12]
 8005f94:	4608      	mov	r0, r1
 8005f96:	f7ff fc1d 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */
 8005f9a:	a908      	add	r1, sp, #32
 8005f9c:	4623      	mov	r3, r4
 8005f9e:	463a      	mov	r2, r7
 8005fa0:	4608      	mov	r0, r1
 8005fa2:	f7ff fc17 	bl	80057d4 <uECC_vli_modMult_fast>
    /* End 1/Z calculation */

    XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
 8005fa6:	9400      	str	r4, [sp, #0]
 8005fa8:	4633      	mov	r3, r6
 8005faa:	463a      	mov	r2, r7
 8005fac:	4629      	mov	r1, r5
 8005fae:	4648      	mov	r0, r9
 8005fb0:	f7ff fdc2 	bl	8005b38 <XYcZ_add>
    apply_z(Rx[0], Ry[0], z, curve);
 8005fb4:	4623      	mov	r3, r4
 8005fb6:	aa08      	add	r2, sp, #32
 8005fb8:	a920      	add	r1, sp, #128	; 0x80
 8005fba:	a810      	add	r0, sp, #64	; 0x40
 8005fbc:	f7ff fc1e 	bl	80057fc <apply_z>
    
    uECC_vli_set(result, Rx[0], num_words);
 8005fc0:	4642      	mov	r2, r8
 8005fc2:	a910      	add	r1, sp, #64	; 0x40
 8005fc4:	9804      	ldr	r0, [sp, #16]
 8005fc6:	f7ff fb29 	bl	800561c <uECC_vli_set>
    uECC_vli_set(result + num_words, Ry[0], num_words);
 8005fca:	9b04      	ldr	r3, [sp, #16]
 8005fcc:	9c02      	ldr	r4, [sp, #8]
 8005fce:	4423      	add	r3, r4
 8005fd0:	4642      	mov	r2, r8
 8005fd2:	a920      	add	r1, sp, #128	; 0x80
 8005fd4:	4618      	mov	r0, r3
 8005fd6:	f7ff fb21 	bl	800561c <uECC_vli_set>
}
 8005fda:	b031      	add	sp, #196	; 0xc4
 8005fdc:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}

08005fe0 <EccPoint_compute_public_key>:
    return carry;
}

static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
                                               uECC_word_t *private,
                                               uECC_Curve curve) {
 8005fe0:	b530      	push	{r4, r5, lr}
 8005fe2:	4614      	mov	r4, r2
 8005fe4:	b095      	sub	sp, #84	; 0x54
 8005fe6:	4605      	mov	r5, r0
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {tmp1, tmp2};
 8005fe8:	aa0c      	add	r2, sp, #48	; 0x30
    uECC_word_t carry;

    /* Regularize the bitcount for the private key so that attackers cannot use a side channel
       attack to learn the number of leading zeros. */
    carry = regularize_k(private, tmp1, tmp2, curve);
 8005fea:	4623      	mov	r3, r4
    return carry;
}

static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
                                               uECC_word_t *private,
                                               uECC_Curve curve) {
 8005fec:	4608      	mov	r0, r1
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {tmp1, tmp2};
 8005fee:	a904      	add	r1, sp, #16
 8005ff0:	9102      	str	r1, [sp, #8]
 8005ff2:	9203      	str	r2, [sp, #12]
    uECC_word_t carry;

    /* Regularize the bitcount for the private key so that attackers cannot use a side channel
       attack to learn the number of leading zeros. */
    carry = regularize_k(private, tmp1, tmp2, curve);
 8005ff4:	f7ff fcd8 	bl	80059a8 <regularize_k>

    EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
 8005ff8:	fab0 f080 	clz	r0, r0
 8005ffc:	ab14      	add	r3, sp, #80	; 0x50
 8005ffe:	0940      	lsrs	r0, r0, #5
 8006000:	eb03 0080 	add.w	r0, r3, r0, lsl #2
 8006004:	8863      	ldrh	r3, [r4, #2]
 8006006:	9401      	str	r4, [sp, #4]
 8006008:	3301      	adds	r3, #1
 800600a:	b21b      	sxth	r3, r3
 800600c:	9300      	str	r3, [sp, #0]
 800600e:	f850 2c48 	ldr.w	r2, [r0, #-72]
 8006012:	2300      	movs	r3, #0
 8006014:	f104 0144 	add.w	r1, r4, #68	; 0x44
 8006018:	4628      	mov	r0, r5
 800601a:	f7ff ff10 	bl	8005e3e <EccPoint_mult>

    if (EccPoint_isZero(result, curve)) {
 800601e:	7821      	ldrb	r1, [r4, #0]
 8006020:	0049      	lsls	r1, r1, #1
 8006022:	b249      	sxtb	r1, r1
 8006024:	4628      	mov	r0, r5
 8006026:	f7ff fabe 	bl	80055a6 <uECC_vli_isZero>
        return 0;
    }
    return 1;
}
 800602a:	fab0 f080 	clz	r0, r0
 800602e:	0940      	lsrs	r0, r0, #5
 8006030:	b015      	add	sp, #84	; 0x54
 8006032:	bd30      	pop	{r4, r5, pc}

08006034 <double_jacobian_secp256k1>:

/* Double in place */
static void double_jacobian_secp256k1(uECC_word_t * X1,
                                      uECC_word_t * Y1,
                                      uECC_word_t * Z1,
                                      uECC_Curve curve) {
 8006034:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
 8006038:	4605      	mov	r5, r0
 800603a:	b093      	sub	sp, #76	; 0x4c
 800603c:	460c      	mov	r4, r1
    /* t1 = X, t2 = Y, t3 = Z */
    uECC_word_t t4[num_words_secp256k1];
    uECC_word_t t5[num_words_secp256k1];
    
    if (uECC_vli_isZero(Z1, num_words_secp256k1)) {
 800603e:	4610      	mov	r0, r2
 8006040:	2108      	movs	r1, #8

/* Double in place */
static void double_jacobian_secp256k1(uECC_word_t * X1,
                                      uECC_word_t * Y1,
                                      uECC_word_t * Z1,
                                      uECC_Curve curve) {
 8006042:	4617      	mov	r7, r2
 8006044:	461e      	mov	r6, r3
    /* t1 = X, t2 = Y, t3 = Z */
    uECC_word_t t4[num_words_secp256k1];
    uECC_word_t t5[num_words_secp256k1];
    
    if (uECC_vli_isZero(Z1, num_words_secp256k1)) {
 8006046:	f7ff faae 	bl	80055a6 <uECC_vli_isZero>
 800604a:	2800      	cmp	r0, #0
 800604c:	d166      	bne.n	800611c <double_jacobian_secp256k1+0xe8>
        return;
    }
    
    uECC_vli_modSquare_fast(t5, Y1, curve);   /* t5 = y1^2 */
 800604e:	4632      	mov	r2, r6
 8006050:	4621      	mov	r1, r4
 8006052:	a80a      	add	r0, sp, #40	; 0x28
 8006054:	f7ff fbce 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
 8006058:	4633      	mov	r3, r6
 800605a:	aa0a      	add	r2, sp, #40	; 0x28
 800605c:	4629      	mov	r1, r5
 800605e:	a802      	add	r0, sp, #8
 8006060:	f7ff fbb8 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSquare_fast(X1, X1, curve);   /* t1 = x1^2 */
 8006064:	4632      	mov	r2, r6
 8006066:	4629      	mov	r1, r5
 8006068:	4628      	mov	r0, r5
 800606a:	f7ff fbc3 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modSquare_fast(t5, t5, curve);   /* t5 = y1^4 */
 800606e:	a90a      	add	r1, sp, #40	; 0x28
 8006070:	4608      	mov	r0, r1
 8006072:	4632      	mov	r2, r6
 8006074:	f7ff fbbe 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
    
    uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
 8006078:	f04f 0808 	mov.w	r8, #8
    
    uECC_vli_modSquare_fast(t5, Y1, curve);   /* t5 = y1^2 */
    uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
    uECC_vli_modSquare_fast(X1, X1, curve);   /* t1 = x1^2 */
    uECC_vli_modSquare_fast(t5, t5, curve);   /* t5 = y1^4 */
    uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
 800607c:	463a      	mov	r2, r7
 800607e:	4638      	mov	r0, r7
 8006080:	4633      	mov	r3, r6
 8006082:	4621      	mov	r1, r4
    
    uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
 8006084:	1d37      	adds	r7, r6, #4
    
    uECC_vli_modSquare_fast(t5, Y1, curve);   /* t5 = y1^2 */
    uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */
    uECC_vli_modSquare_fast(X1, X1, curve);   /* t1 = x1^2 */
    uECC_vli_modSquare_fast(t5, t5, curve);   /* t5 = y1^4 */
    uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
 8006086:	f7ff fba5 	bl	80057d4 <uECC_vli_modMult_fast>
    
    uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
 800608a:	463b      	mov	r3, r7
 800608c:	462a      	mov	r2, r5
 800608e:	4629      	mov	r1, r5
 8006090:	4620      	mov	r0, r4
 8006092:	f8cd 8000 	str.w	r8, [sp]
 8006096:	f7ff fcd5 	bl	8005a44 <uECC_vli_modAdd>
    uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
 800609a:	463b      	mov	r3, r7
 800609c:	f8cd 8000 	str.w	r8, [sp]
 80060a0:	462a      	mov	r2, r5
 80060a2:	4621      	mov	r1, r4
 80060a4:	4620      	mov	r0, r4
 80060a6:	f7ff fccd 	bl	8005a44 <uECC_vli_modAdd>
    if (uECC_vli_testBit(Y1, 0)) {
 80060aa:	6823      	ldr	r3, [r4, #0]
 80060ac:	07db      	lsls	r3, r3, #31
 80060ae:	d50e      	bpl.n	80060ce <double_jacobian_secp256k1+0x9a>
        uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
 80060b0:	463a      	mov	r2, r7
 80060b2:	4621      	mov	r1, r4
 80060b4:	4620      	mov	r0, r4
 80060b6:	f7ff fbf5 	bl	80058a4 <uECC_vli_add.isra.0>
        uECC_vli_rshift1(Y1, num_words_secp256k1);
 80060ba:	4641      	mov	r1, r8
    uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */
    
    uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */
    uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */
    if (uECC_vli_testBit(Y1, 0)) {
        uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1);
 80060bc:	4681      	mov	r9, r0
        uECC_vli_rshift1(Y1, num_words_secp256k1);
 80060be:	4620      	mov	r0, r4
 80060c0:	f7ff face 	bl	8005660 <uECC_vli_rshift1>
        Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1);
 80060c4:	69e0      	ldr	r0, [r4, #28]
 80060c6:	ea40 70c9 	orr.w	r0, r0, r9, lsl #31
 80060ca:	61e0      	str	r0, [r4, #28]
 80060cc:	e003      	b.n	80060d6 <double_jacobian_secp256k1+0xa2>
    } else {
        uECC_vli_rshift1(Y1, num_words_secp256k1);
 80060ce:	4641      	mov	r1, r8
 80060d0:	4620      	mov	r0, r4
 80060d2:	f7ff fac5 	bl	8005660 <uECC_vli_rshift1>
    }
    /* t2 = 3/2*(x1^2) = B */
    
    uECC_vli_modSquare_fast(X1, Y1, curve);                     /* t1 = B^2 */
 80060d6:	4632      	mov	r2, r6
 80060d8:	4621      	mov	r1, r4
 80060da:	4628      	mov	r0, r5
 80060dc:	f7ff fb8a 	bl	80057f4 <uECC_vli_modSquare_fast>
    uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */
 80060e0:	463b      	mov	r3, r7
 80060e2:	aa02      	add	r2, sp, #8
 80060e4:	4629      	mov	r1, r5
 80060e6:	4628      	mov	r0, r5
 80060e8:	f7ff fd18 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */
 80060ec:	463b      	mov	r3, r7
 80060ee:	aa02      	add	r2, sp, #8
 80060f0:	4629      	mov	r1, r5
 80060f2:	4628      	mov	r0, r5
 80060f4:	f7ff fd12 	bl	8005b1c <uECC_vli_modSub.isra.2>
    
    uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */
 80060f8:	a902      	add	r1, sp, #8
 80060fa:	4608      	mov	r0, r1
 80060fc:	463b      	mov	r3, r7
 80060fe:	462a      	mov	r2, r5
 8006100:	f7ff fd0c 	bl	8005b1c <uECC_vli_modSub.isra.2>
    uECC_vli_modMult_fast(Y1, Y1, t4, curve);                   /* t2 = B * (A - x3) */
 8006104:	4633      	mov	r3, r6
 8006106:	aa02      	add	r2, sp, #8
 8006108:	4621      	mov	r1, r4
 800610a:	4620      	mov	r0, r4
 800610c:	f7ff fb62 	bl	80057d4 <uECC_vli_modMult_fast>
    uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */
 8006110:	463b      	mov	r3, r7
 8006112:	aa0a      	add	r2, sp, #40	; 0x28
 8006114:	4621      	mov	r1, r4
 8006116:	4620      	mov	r0, r4
 8006118:	f7ff fd00 	bl	8005b1c <uECC_vli_modSub.isra.2>
}
 800611c:	b013      	add	sp, #76	; 0x4c
 800611e:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}
	...

08006124 <uECC_generate_random_int>:

/* Generates a random integer in the range 0 < random < top.
   Both random and top have num_words words. */
uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
                                          const uECC_word_t *top,
                                          wordcount_t num_words) {
 8006124:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
 8006128:	468a      	mov	sl, r1
    uECC_word_t mask = (uECC_word_t)-1;
    uECC_word_t tries;
    bitcount_t num_bits = uECC_vli_numBits(top, num_words);

    if (!g_rng_function) {
 800612a:	4f24      	ldr	r7, [pc, #144]	; (80061bc <uECC_generate_random_int+0x98>)

/* Generates a random integer in the range 0 < random < top.
   Both random and top have num_words words. */
uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
                                          const uECC_word_t *top,
                                          wordcount_t num_words) {
 800612c:	b08b      	sub	sp, #44	; 0x2c
 800612e:	4606      	mov	r6, r0
    uECC_word_t mask = (uECC_word_t)-1;
    uECC_word_t tries;
    bitcount_t num_bits = uECC_vli_numBits(top, num_words);
 8006130:	4611      	mov	r1, r2
 8006132:	4650      	mov	r0, sl

/* Generates a random integer in the range 0 < random < top.
   Both random and top have num_words words. */
uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random,
                                          const uECC_word_t *top,
                                          wordcount_t num_words) {
 8006134:	4615      	mov	r5, r2
    uECC_word_t mask = (uECC_word_t)-1;
    uECC_word_t tries;
    bitcount_t num_bits = uECC_vli_numBits(top, num_words);
 8006136:	f7ff fa4f 	bl	80055d8 <uECC_vli_numBits>

    if (!g_rng_function) {
 800613a:	683b      	ldr	r3, [r7, #0]
 800613c:	b90b      	cbnz	r3, 8006142 <uECC_generate_random_int+0x1e>
        return 0;
 800613e:	2000      	movs	r0, #0
 8006140:	e038      	b.n	80061b4 <uECC_generate_random_int+0x90>
    }

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
 8006142:	2404      	movs	r4, #4
            return 0;
	    }
        random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
 8006144:	ebc0 1045 	rsb	r0, r0, r5, lsl #5
    if (!g_rng_function) {
        return 0;
    }

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
 8006148:	fb15 fb04 	smulbb	fp, r5, r4
            return 0;
	    }
        random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
 800614c:	b200      	sxth	r0, r0
 800614e:	fb04 6405 	mla	r4, r4, r5, r6
 8006152:	f04f 39ff 	mov.w	r9, #4294967295	; 0xffffffff
 8006156:	3c04      	subs	r4, #4
 8006158:	fa29 f900 	lsr.w	r9, r9, r0
 800615c:	f04f 0840 	mov.w	r8, #64	; 0x40
    if (!g_rng_function) {
        return 0;
    }

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
 8006160:	683b      	ldr	r3, [r7, #0]
 8006162:	4659      	mov	r1, fp
 8006164:	4630      	mov	r0, r6
 8006166:	4798      	blx	r3
 8006168:	2800      	cmp	r0, #0
 800616a:	d0e8      	beq.n	800613e <uECC_generate_random_int+0x1a>
            return 0;
	    }
        random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
 800616c:	6823      	ldr	r3, [r4, #0]
 800616e:	ea03 0309 	and.w	r3, r3, r9
 8006172:	6023      	str	r3, [r4, #0]
        if (!uECC_vli_isZero(random, num_words) &&
 8006174:	4629      	mov	r1, r5
 8006176:	4630      	mov	r0, r6
 8006178:	f7ff fa15 	bl	80055a6 <uECC_vli_isZero>
 800617c:	b118      	cbz	r0, 8006186 <uECC_generate_random_int+0x62>

    if (!g_rng_function) {
        return 0;
    }

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
 800617e:	f1b8 0801 	subs.w	r8, r8, #1
 8006182:	d1ed      	bne.n	8006160 <uECC_generate_random_int+0x3c>
 8006184:	e7db      	b.n	800613e <uECC_generate_random_int+0x1a>
/* Returns sign of left - right, in constant time. */
uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
                                      const uECC_word_t *right,
                                      wordcount_t num_words) {
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
 8006186:	4632      	mov	r2, r6
 8006188:	4651      	mov	r1, sl
 800618a:	a802      	add	r0, sp, #8
 800618c:	f7ff fc33 	bl	80059f6 <uECC_vli_sub.isra.1>
    uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
 8006190:	4629      	mov	r1, r5
/* Returns sign of left - right, in constant time. */
uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
                                      const uECC_word_t *right,
                                      wordcount_t num_words) {
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
 8006192:	9001      	str	r0, [sp, #4]
    uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
 8006194:	a802      	add	r0, sp, #8
 8006196:	f7ff fa06 	bl	80055a6 <uECC_vli_isZero>
    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
            return 0;
	    }
        random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
        if (!uECC_vli_isZero(random, num_words) &&
 800619a:	9b01      	ldr	r3, [sp, #4]
 800619c:	3300      	adds	r3, #0
 800619e:	bf18      	it	ne
 80061a0:	2301      	movne	r3, #1
 80061a2:	005b      	lsls	r3, r3, #1
 80061a4:	2800      	cmp	r0, #0
 80061a6:	bf14      	ite	ne
 80061a8:	4258      	negne	r0, r3
 80061aa:	f1c3 0001 	rsbeq	r0, r3, #1
 80061ae:	b2c0      	uxtb	r0, r0
 80061b0:	2801      	cmp	r0, #1
 80061b2:	d1e4      	bne.n	800617e <uECC_generate_random_int+0x5a>
		        uECC_vli_cmp(top, random, num_words) == 1) {
            return 1;
        }
    }
    return 0;
}
 80061b4:	b00b      	add	sp, #44	; 0x2c
 80061b6:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}
 80061ba:	bf00      	nop
 80061bc:	10006344 	.word	0x10006344

080061c0 <uECC_set_rng>:

// PDG: added prototype
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);

void uECC_set_rng(uECC_RNG_Function rng_function) {
    g_rng_function = rng_function;
 80061c0:	4b01      	ldr	r3, [pc, #4]	; (80061c8 <uECC_set_rng+0x8>)
 80061c2:	6018      	str	r0, [r3, #0]
 80061c4:	4770      	bx	lr
 80061c6:	bf00      	nop
 80061c8:	10006344 	.word	0x10006344

080061cc <uECC_secp256k1>:
#if (uECC_OPTIMIZATION_LEVEL > 0)
    &vli_mmod_fast_secp256k1
#endif
};

uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; }
 80061cc:	4800      	ldr	r0, [pc, #0]	; (80061d0 <uECC_secp256k1+0x4>)
 80061ce:	4770      	bx	lr
 80061d0:	080074d4 	.word	0x080074d4

080061d4 <uECC_make_key>:
    return 0;
}

int uECC_make_key(uint8_t *public_key,
                  uint8_t *private_key,
                  uECC_Curve curve) {
 80061d4:	e92d 43f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, lr}
 80061d8:	4606      	mov	r6, r0
 80061da:	b099      	sub	sp, #100	; 0x64
 80061dc:	460f      	mov	r7, r1
 80061de:	4614      	mov	r4, r2
 80061e0:	2540      	movs	r5, #64	; 0x40
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t public[uECC_MAX_WORDS * 2];
    uECC_word_t tries;

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
        if (!uECC_generate_random_int(private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) {
 80061e2:	f04f 0820 	mov.w	r8, #32
 80061e6:	f102 0924 	add.w	r9, r2, #36	; 0x24
 80061ea:	f9b4 2002 	ldrsh.w	r2, [r4, #2]
 80061ee:	4649      	mov	r1, r9
 80061f0:	321f      	adds	r2, #31
 80061f2:	4668      	mov	r0, sp
 80061f4:	fb92 f2f8 	sdiv	r2, r2, r8
 80061f8:	b252      	sxtb	r2, r2
 80061fa:	f7ff ff93 	bl	8006124 <uECC_generate_random_int>
 80061fe:	b908      	cbnz	r0, 8006204 <uECC_make_key+0x30>
            return 0;
 8006200:	2000      	movs	r0, #0
 8006202:	e024      	b.n	800624e <uECC_make_key+0x7a>
        }

        if (EccPoint_compute_public_key(public, private, curve)) {
 8006204:	4622      	mov	r2, r4
 8006206:	4669      	mov	r1, sp
 8006208:	a808      	add	r0, sp, #32
 800620a:	f7ff fee9 	bl	8005fe0 <EccPoint_compute_public_key>
 800620e:	b1d8      	cbz	r0, 8006248 <uECC_make_key+0x74>
            uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), private);
 8006210:	f9b4 3002 	ldrsh.w	r3, [r4, #2]
 8006214:	466a      	mov	r2, sp
 8006216:	3307      	adds	r3, #7
 8006218:	4638      	mov	r0, r7
 800621a:	2108      	movs	r1, #8
 800621c:	fb93 f1f1 	sdiv	r1, r3, r1
 8006220:	f7ff fb0b 	bl	800583a <uECC_vli_nativeToBytes>
            uECC_vli_nativeToBytes(public_key, curve->num_bytes, public);
 8006224:	aa08      	add	r2, sp, #32
 8006226:	f994 1001 	ldrsb.w	r1, [r4, #1]
 800622a:	4630      	mov	r0, r6
 800622c:	f7ff fb05 	bl	800583a <uECC_vli_nativeToBytes>
            uECC_vli_nativeToBytes(
 8006230:	f994 2000 	ldrsb.w	r2, [r4]
 8006234:	f994 1001 	ldrsb.w	r1, [r4, #1]
 8006238:	ab08      	add	r3, sp, #32
 800623a:	1870      	adds	r0, r6, r1
 800623c:	eb03 0282 	add.w	r2, r3, r2, lsl #2
 8006240:	f7ff fafb 	bl	800583a <uECC_vli_nativeToBytes>
                public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words);
            return 1;
 8006244:	2001      	movs	r0, #1
 8006246:	e002      	b.n	800624e <uECC_make_key+0x7a>
                  uECC_Curve curve) {
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t public[uECC_MAX_WORDS * 2];
    uECC_word_t tries;

    for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
 8006248:	3d01      	subs	r5, #1
 800624a:	d1ce      	bne.n	80061ea <uECC_make_key+0x16>
 800624c:	e7d8      	b.n	8006200 <uECC_make_key+0x2c>
                public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words);
            return 1;
        }
    }
    return 0;
}
 800624e:	b019      	add	sp, #100	; 0x64
 8006250:	e8bd 83f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, pc}

08006254 <uECC_shared_secret>:

int uECC_shared_secret(const uint8_t *public_key,
                       const uint8_t *private_key,
                       uint8_t *secret,
                       uECC_Curve curve) {
 8006254:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
 8006258:	461c      	mov	r4, r3
 800625a:	b0a4      	sub	sp, #144	; 0x90
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {private, tmp};
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
 800625c:	f893 9000 	ldrb.w	r9, [r3]
    wordcount_t num_bytes = curve->num_bytes;
 8006260:	785e      	ldrb	r6, [r3, #1]
    
    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 8006262:	f9b3 3002 	ldrsh.w	r3, [r3, #2]
                       uint8_t *secret,
                       uECC_Curve curve) {
    uECC_word_t public[uECC_MAX_WORDS * 2];
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {private, tmp};
 8006266:	ad04      	add	r5, sp, #16
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_bytes = curve->num_bytes;
    
    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 8006268:	3307      	adds	r3, #7
}

int uECC_shared_secret(const uint8_t *public_key,
                       const uint8_t *private_key,
                       uint8_t *secret,
                       uECC_Curve curve) {
 800626a:	4682      	mov	sl, r0
    uECC_word_t public[uECC_MAX_WORDS * 2];
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {private, tmp};
 800626c:	af0c      	add	r7, sp, #48	; 0x30
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_bytes = curve->num_bytes;
    
    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 800626e:	4628      	mov	r0, r5
    uECC_vli_bytesToNative(public, public_key, num_bytes);
 8006270:	b276      	sxtb	r6, r6
}

int uECC_shared_secret(const uint8_t *public_key,
                       const uint8_t *private_key,
                       uint8_t *secret,
                       uECC_Curve curve) {
 8006272:	4690      	mov	r8, r2
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_bytes = curve->num_bytes;
    
    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 8006274:	2208      	movs	r2, #8
 8006276:	fb93 f2f2 	sdiv	r2, r3, r2
                       uint8_t *secret,
                       uECC_Curve curve) {
    uECC_word_t public[uECC_MAX_WORDS * 2];
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t *p2[2] = {private, tmp};
 800627a:	9502      	str	r5, [sp, #8]
 800627c:	9703      	str	r7, [sp, #12]
    uECC_word_t *initial_Z = 0;
    uECC_word_t carry;
    wordcount_t num_words = curve->num_words;
    wordcount_t num_bytes = curve->num_bytes;
    
    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 800627e:	f7ff faf0 	bl	8005862 <uECC_vli_bytesToNative>
    uECC_vli_bytesToNative(public, public_key, num_bytes);
 8006282:	4632      	mov	r2, r6
 8006284:	4651      	mov	r1, sl
 8006286:	a814      	add	r0, sp, #80	; 0x50
 8006288:	f7ff faeb 	bl	8005862 <uECC_vli_bytesToNative>
    uECC_vli_bytesToNative(public + num_words, public_key + num_bytes, num_bytes);
 800628c:	fa4f f989 	sxtb.w	r9, r9
 8006290:	ab14      	add	r3, sp, #80	; 0x50
 8006292:	eb03 0089 	add.w	r0, r3, r9, lsl #2
 8006296:	4632      	mov	r2, r6
 8006298:	eb0a 0106 	add.w	r1, sl, r6
 800629c:	f7ff fae1 	bl	8005862 <uECC_vli_bytesToNative>
    
    /* Regularize the bitcount for the private key so that attackers cannot use a side channel
       attack to learn the number of leading zeros. */
    carry = regularize_k(private, private, tmp, curve);
 80062a0:	4623      	mov	r3, r4
 80062a2:	463a      	mov	r2, r7
 80062a4:	4629      	mov	r1, r5
 80062a6:	4628      	mov	r0, r5
 80062a8:	f7ff fb7e 	bl	80059a8 <regularize_k>
    
    /* If an RNG function was specified, try to get a random initial Z value to improve
       protection against side-channel attacks. */
    if (g_rng_function) {
 80062ac:	4b18      	ldr	r3, [pc, #96]	; (8006310 <uECC_shared_secret+0xbc>)
 80062ae:	681f      	ldr	r7, [r3, #0]
    uECC_vli_bytesToNative(public, public_key, num_bytes);
    uECC_vli_bytesToNative(public + num_words, public_key + num_bytes, num_bytes);
    
    /* Regularize the bitcount for the private key so that attackers cannot use a side channel
       attack to learn the number of leading zeros. */
    carry = regularize_k(private, private, tmp, curve);
 80062b0:	4605      	mov	r5, r0
    
    /* If an RNG function was specified, try to get a random initial Z value to improve
       protection against side-channel attacks. */
    if (g_rng_function) {
 80062b2:	b157      	cbz	r7, 80062ca <uECC_shared_secret+0x76>
        if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
 80062b4:	ab24      	add	r3, sp, #144	; 0x90
 80062b6:	eb03 0380 	add.w	r3, r3, r0, lsl #2
 80062ba:	464a      	mov	r2, r9
 80062bc:	f853 7c88 	ldr.w	r7, [r3, #-136]
 80062c0:	1d21      	adds	r1, r4, #4
 80062c2:	4638      	mov	r0, r7
 80062c4:	f7ff ff2e 	bl	8006124 <uECC_generate_random_int>
 80062c8:	b1f8      	cbz	r0, 800630a <uECC_shared_secret+0xb6>
            return 0;
        }
        initial_Z = p2[carry];
    }
    
    EccPoint_mult(public, public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve);
 80062ca:	fab5 f085 	clz	r0, r5
 80062ce:	ab24      	add	r3, sp, #144	; 0x90
 80062d0:	0940      	lsrs	r0, r0, #5
 80062d2:	eb03 0080 	add.w	r0, r3, r0, lsl #2
 80062d6:	8863      	ldrh	r3, [r4, #2]
 80062d8:	9401      	str	r4, [sp, #4]
 80062da:	3301      	adds	r3, #1
 80062dc:	b21b      	sxth	r3, r3
 80062de:	9300      	str	r3, [sp, #0]
 80062e0:	a914      	add	r1, sp, #80	; 0x50
 80062e2:	463b      	mov	r3, r7
 80062e4:	f850 2c88 	ldr.w	r2, [r0, #-136]
 80062e8:	4608      	mov	r0, r1
 80062ea:	f7ff fda8 	bl	8005e3e <EccPoint_mult>
    uECC_vli_nativeToBytes(secret, num_bytes, public);
 80062ee:	aa14      	add	r2, sp, #80	; 0x50
 80062f0:	4631      	mov	r1, r6
 80062f2:	4640      	mov	r0, r8
 80062f4:	f7ff faa1 	bl	800583a <uECC_vli_nativeToBytes>
    return !EccPoint_isZero(public, curve);
 80062f8:	7821      	ldrb	r1, [r4, #0]
 80062fa:	0049      	lsls	r1, r1, #1
 80062fc:	b249      	sxtb	r1, r1
 80062fe:	a814      	add	r0, sp, #80	; 0x50
 8006300:	f7ff f951 	bl	80055a6 <uECC_vli_isZero>
 8006304:	fab0 f080 	clz	r0, r0
 8006308:	0940      	lsrs	r0, r0, #5
}
 800630a:	b024      	add	sp, #144	; 0x90
 800630c:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}
 8006310:	10006344 	.word	0x10006344

08006314 <uECC_compress>:

#if uECC_SUPPORT_COMPRESSED_POINT
void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) {
 8006314:	b530      	push	{r4, r5, lr}
    wordcount_t i;
    for (i = 0; i < curve->num_bytes; ++i) {
 8006316:	2400      	movs	r4, #0
 8006318:	b2e3      	uxtb	r3, r4
 800631a:	f992 5001 	ldrsb.w	r5, [r2, #1]
 800631e:	b25b      	sxtb	r3, r3
 8006320:	42ab      	cmp	r3, r5
 8006322:	f104 0401 	add.w	r4, r4, #1
 8006326:	da03      	bge.n	8006330 <uECC_compress+0x1c>
        compressed[i+1] = public_key[i];
 8006328:	5cc5      	ldrb	r5, [r0, r3]
 800632a:	440b      	add	r3, r1
 800632c:	705d      	strb	r5, [r3, #1]
 800632e:	e7f3      	b.n	8006318 <uECC_compress+0x4>
    }
    compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
 8006330:	eb00 0045 	add.w	r0, r0, r5, lsl #1
 8006334:	f810 3c01 	ldrb.w	r3, [r0, #-1]
 8006338:	f003 0301 	and.w	r3, r3, #1
 800633c:	3302      	adds	r3, #2
 800633e:	700b      	strb	r3, [r1, #0]
 8006340:	bd30      	pop	{r4, r5, pc}

08006342 <uECC_decompress>:
}

void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
 8006342:	e92d 41f0 	stmdb	sp!, {r4, r5, r6, r7, r8, lr}
    uECC_word_t point[uECC_MAX_WORDS * 2];
    uECC_word_t *y = point + curve->num_words;
 8006346:	f992 7000 	ldrsb.w	r7, [r2]
        compressed[i+1] = public_key[i];
    }
    compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
}

void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
 800634a:	b090      	sub	sp, #64	; 0x40
 800634c:	4614      	mov	r4, r2
 800634e:	4680      	mov	r8, r0
    uECC_word_t point[uECC_MAX_WORDS * 2];
    uECC_word_t *y = point + curve->num_words;
 8006350:	eb0d 0587 	add.w	r5, sp, r7, lsl #2
    uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes);
 8006354:	f992 2001 	ldrsb.w	r2, [r2, #1]
        compressed[i+1] = public_key[i];
    }
    compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01);
}

void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) {
 8006358:	460e      	mov	r6, r1
    uECC_word_t point[uECC_MAX_WORDS * 2];
    uECC_word_t *y = point + curve->num_words;
    uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes);
 800635a:	1c41      	adds	r1, r0, #1
 800635c:	4668      	mov	r0, sp
 800635e:	f7ff fa80 	bl	8005862 <uECC_vli_bytesToNative>
    curve->x_side(y, point, curve);
 8006362:	4622      	mov	r2, r4
 8006364:	f8d4 30ac 	ldr.w	r3, [r4, #172]	; 0xac
 8006368:	4669      	mov	r1, sp
 800636a:	4628      	mov	r0, r5
 800636c:	4798      	blx	r3
    curve->mod_sqrt(y, curve);
 800636e:	f8d4 30a8 	ldr.w	r3, [r4, #168]	; 0xa8
 8006372:	4621      	mov	r1, r4
 8006374:	4628      	mov	r0, r5
 8006376:	4798      	blx	r3
    
    if ((y[0] & 0x01) != (compressed[0] & 0x01)) {
 8006378:	f898 2000 	ldrb.w	r2, [r8]
 800637c:	f85d 3027 	ldr.w	r3, [sp, r7, lsl #2]
 8006380:	4053      	eors	r3, r2
 8006382:	07db      	lsls	r3, r3, #31
 8006384:	d504      	bpl.n	8006390 <uECC_decompress+0x4e>
        uECC_vli_sub(y, curve->p, y, curve->num_words);
 8006386:	462a      	mov	r2, r5
 8006388:	1d21      	adds	r1, r4, #4
 800638a:	4628      	mov	r0, r5
 800638c:	f7ff fb33 	bl	80059f6 <uECC_vli_sub.isra.1>
    }
    
    uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
 8006390:	466a      	mov	r2, sp
 8006392:	f994 1001 	ldrsb.w	r1, [r4, #1]
 8006396:	4630      	mov	r0, r6
 8006398:	f7ff fa4f 	bl	800583a <uECC_vli_nativeToBytes>
    uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
 800639c:	f994 1001 	ldrsb.w	r1, [r4, #1]
 80063a0:	462a      	mov	r2, r5
 80063a2:	1870      	adds	r0, r6, r1
 80063a4:	f7ff fa49 	bl	800583a <uECC_vli_nativeToBytes>
}
 80063a8:	b010      	add	sp, #64	; 0x40
 80063aa:	e8bd 81f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, pc}

080063ae <uECC_valid_point>:
#endif /* uECC_SUPPORT_COMPRESSED_POINT */

int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
 80063ae:	e92d 47f0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, lr}
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
 80063b2:	780e      	ldrb	r6, [r1, #0]

    /* The point at infinity is invalid. */
    if (EccPoint_isZero(point, curve)) {
 80063b4:	b2f5      	uxtb	r5, r6
    uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
    uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
}
#endif /* uECC_SUPPORT_COMPRESSED_POINT */

int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
 80063b6:	460f      	mov	r7, r1
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;

    /* The point at infinity is invalid. */
    if (EccPoint_isZero(point, curve)) {
 80063b8:	0069      	lsls	r1, r5, #1
    uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
    uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
}
#endif /* uECC_SUPPORT_COMPRESSED_POINT */

int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
 80063ba:	b090      	sub	sp, #64	; 0x40
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;

    /* The point at infinity is invalid. */
    if (EccPoint_isZero(point, curve)) {
 80063bc:	b249      	sxtb	r1, r1
    uECC_vli_nativeToBytes(public_key, curve->num_bytes, point);
    uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y);
}
#endif /* uECC_SUPPORT_COMPRESSED_POINT */

int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) {
 80063be:	4680      	mov	r8, r0
    uECC_word_t tmp1[uECC_MAX_WORDS];
    uECC_word_t tmp2[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;

    /* The point at infinity is invalid. */
    if (EccPoint_isZero(point, curve)) {
 80063c0:	f7ff f8f1 	bl	80055a6 <uECC_vli_isZero>
 80063c4:	4604      	mov	r4, r0
 80063c6:	bb98      	cbnz	r0, 8006430 <uECC_valid_point+0x82>
        return 0;
    }
    
    /* x and y must be smaller than p. */
    if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
 80063c8:	f107 0a04 	add.w	sl, r7, #4
 80063cc:	b276      	sxtb	r6, r6
 80063ce:	4632      	mov	r2, r6
 80063d0:	4641      	mov	r1, r8
 80063d2:	4650      	mov	r0, sl
 80063d4:	f7ff f92f 	bl	8005636 <uECC_vli_cmp_unsafe>
 80063d8:	2801      	cmp	r0, #1
 80063da:	d12b      	bne.n	8006434 <uECC_valid_point+0x86>
            uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
 80063dc:	eb08 0986 	add.w	r9, r8, r6, lsl #2
 80063e0:	4632      	mov	r2, r6
 80063e2:	4649      	mov	r1, r9
 80063e4:	4650      	mov	r0, sl
 80063e6:	f7ff f926 	bl	8005636 <uECC_vli_cmp_unsafe>
    if (EccPoint_isZero(point, curve)) {
        return 0;
    }
    
    /* x and y must be smaller than p. */
    if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
 80063ea:	2801      	cmp	r0, #1
 80063ec:	d122      	bne.n	8006434 <uECC_valid_point+0x86>
            uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
        return 0;
    }
    
    uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
 80063ee:	463a      	mov	r2, r7
 80063f0:	4649      	mov	r1, r9
 80063f2:	4668      	mov	r0, sp
 80063f4:	f7ff f9fe 	bl	80057f4 <uECC_vli_modSquare_fast>
    curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
 80063f8:	f8d7 30ac 	ldr.w	r3, [r7, #172]	; 0xac
 80063fc:	a808      	add	r0, sp, #32
 80063fe:	463a      	mov	r2, r7
 8006400:	4641      	mov	r1, r8
 8006402:	4798      	blx	r3
uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
                                        const uECC_word_t *right,
                                        wordcount_t num_words) {
    uECC_word_t diff = 0;
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
 8006404:	1e6b      	subs	r3, r5, #1
 8006406:	b2db      	uxtb	r3, r3
/* Constant-time comparison function - secure way to compare long integers */
/* Returns one if left == right, zero otherwise. */
uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
                                        const uECC_word_t *right,
                                        wordcount_t num_words) {
    uECC_word_t diff = 0;
 8006408:	4620      	mov	r0, r4
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
 800640a:	b25a      	sxtb	r2, r3
 800640c:	2a00      	cmp	r2, #0
 800640e:	db0b      	blt.n	8006428 <uECC_valid_point+0x7a>
        diff |= (left[i] ^ right[i]);
 8006410:	a910      	add	r1, sp, #64	; 0x40
 8006412:	eb01 0282 	add.w	r2, r1, r2, lsl #2
 8006416:	3b01      	subs	r3, #1
 8006418:	f852 1c40 	ldr.w	r1, [r2, #-64]
 800641c:	f852 2c20 	ldr.w	r2, [r2, #-32]
 8006420:	404a      	eors	r2, r1
 8006422:	4310      	orrs	r0, r2
 8006424:	b2db      	uxtb	r3, r3
 8006426:	e7f0      	b.n	800640a <uECC_valid_point+0x5c>
    
    uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
    curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
    
    /* Make sure that y^2 == x^3 + ax + b */
    return (int)(uECC_vli_equal(tmp1, tmp2, num_words));
 8006428:	fab0 f080 	clz	r0, r0
 800642c:	0940      	lsrs	r0, r0, #5
 800642e:	e002      	b.n	8006436 <uECC_valid_point+0x88>
    uECC_word_t tmp2[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;

    /* The point at infinity is invalid. */
    if (EccPoint_isZero(point, curve)) {
        return 0;
 8006430:	2000      	movs	r0, #0
 8006432:	e000      	b.n	8006436 <uECC_valid_point+0x88>
 8006434:	4620      	mov	r0, r4
    uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
    curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
    
    /* Make sure that y^2 == x^3 + ax + b */
    return (int)(uECC_vli_equal(tmp1, tmp2, num_words));
}
 8006436:	b010      	add	sp, #64	; 0x40
 8006438:	e8bd 87f0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, pc}

0800643c <uECC_valid_public_key>:

int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) {
 800643c:	b530      	push	{r4, r5, lr}
 800643e:	460c      	mov	r4, r1
 8006440:	b091      	sub	sp, #68	; 0x44
 8006442:	4605      	mov	r5, r0
    uECC_word_t public[uECC_MAX_WORDS * 2];

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
 8006444:	f991 2001 	ldrsb.w	r2, [r1, #1]
 8006448:	4601      	mov	r1, r0
 800644a:	4668      	mov	r0, sp
 800644c:	f7ff fa09 	bl	8005862 <uECC_vli_bytesToNative>
    uECC_vli_bytesToNative(
 8006450:	f994 2001 	ldrsb.w	r2, [r4, #1]
 8006454:	f994 0000 	ldrsb.w	r0, [r4]
 8006458:	18a9      	adds	r1, r5, r2
 800645a:	eb0d 0080 	add.w	r0, sp, r0, lsl #2
 800645e:	f7ff fa00 	bl	8005862 <uECC_vli_bytesToNative>
        public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes);
    return uECC_valid_point(public, curve);
 8006462:	4621      	mov	r1, r4
 8006464:	4668      	mov	r0, sp
 8006466:	f7ff ffa2 	bl	80063ae <uECC_valid_point>
}
 800646a:	b011      	add	sp, #68	; 0x44
 800646c:	bd30      	pop	{r4, r5, pc}

0800646e <uECC_compute_public_key>:

int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) {
 800646e:	b5f0      	push	{r4, r5, r6, r7, lr}
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t public[uECC_MAX_WORDS * 2];

    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 8006470:	f9b2 3002 	ldrsh.w	r3, [r2, #2]
    uECC_vli_bytesToNative(
        public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes);
    return uECC_valid_point(public, curve);
}

int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) {
 8006474:	b099      	sub	sp, #100	; 0x64
 8006476:	4616      	mov	r6, r2
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t public[uECC_MAX_WORDS * 2];

    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 8006478:	3307      	adds	r3, #7
    uECC_vli_bytesToNative(
        public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes);
    return uECC_valid_point(public, curve);
}

int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) {
 800647a:	460f      	mov	r7, r1
    uECC_word_t private[uECC_MAX_WORDS];
    uECC_word_t public[uECC_MAX_WORDS * 2];

    uECC_vli_bytesToNative(private, private_key, BITS_TO_BYTES(curve->num_n_bits));
 800647c:	2208      	movs	r2, #8
 800647e:	4601      	mov	r1, r0
 8006480:	fb93 f2f2 	sdiv	r2, r3, r2
 8006484:	4668      	mov	r0, sp
 8006486:	f7ff f9ec 	bl	8005862 <uECC_vli_bytesToNative>

    /* Make sure the private key is in the range [1, n-1]. */
    if (uECC_vli_isZero(private, BITS_TO_WORDS(curve->num_n_bits))) {
 800648a:	f9b6 5002 	ldrsh.w	r5, [r6, #2]
 800648e:	2320      	movs	r3, #32
 8006490:	351f      	adds	r5, #31
 8006492:	fb95 f5f3 	sdiv	r5, r5, r3
 8006496:	b26d      	sxtb	r5, r5
 8006498:	4629      	mov	r1, r5
 800649a:	4668      	mov	r0, sp
 800649c:	f7ff f883 	bl	80055a6 <uECC_vli_isZero>
 80064a0:	b108      	cbz	r0, 80064a6 <uECC_compute_public_key+0x38>
        return 0;
 80064a2:	2000      	movs	r0, #0
 80064a4:	e02e      	b.n	8006504 <uECC_compute_public_key+0x96>
/* Returns sign of left - right, in constant time. */
uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
                                      const uECC_word_t *right,
                                      wordcount_t num_words) {
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
 80064a6:	466a      	mov	r2, sp
 80064a8:	f106 0124 	add.w	r1, r6, #36	; 0x24
 80064ac:	a808      	add	r0, sp, #32
 80064ae:	f7ff faa2 	bl	80059f6 <uECC_vli_sub.isra.1>
    uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
 80064b2:	4629      	mov	r1, r5
/* Returns sign of left - right, in constant time. */
uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left,
                                      const uECC_word_t *right,
                                      wordcount_t num_words) {
    uECC_word_t tmp[uECC_MAX_WORDS];
    uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
 80064b4:	4604      	mov	r4, r0
    uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
 80064b6:	a808      	add	r0, sp, #32
 80064b8:	f7ff f875 	bl	80055a6 <uECC_vli_isZero>
    /* Make sure the private key is in the range [1, n-1]. */
    if (uECC_vli_isZero(private, BITS_TO_WORDS(curve->num_n_bits))) {
        return 0;
    }

    if (uECC_vli_cmp(curve->n, private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
 80064bc:	3400      	adds	r4, #0
 80064be:	bf18      	it	ne
 80064c0:	2401      	movne	r4, #1
 80064c2:	0064      	lsls	r4, r4, #1
 80064c4:	2800      	cmp	r0, #0
 80064c6:	bf14      	ite	ne
 80064c8:	4260      	negne	r0, r4
 80064ca:	f1c4 0001 	rsbeq	r0, r4, #1
 80064ce:	b2c4      	uxtb	r4, r0
 80064d0:	2c01      	cmp	r4, #1
 80064d2:	d1e6      	bne.n	80064a2 <uECC_compute_public_key+0x34>
        return 0;
    }

    /* Compute public key. */
    if (!EccPoint_compute_public_key(public, private, curve)) {
 80064d4:	4632      	mov	r2, r6
 80064d6:	4669      	mov	r1, sp
 80064d8:	a808      	add	r0, sp, #32
 80064da:	f7ff fd81 	bl	8005fe0 <EccPoint_compute_public_key>
 80064de:	2800      	cmp	r0, #0
 80064e0:	d0df      	beq.n	80064a2 <uECC_compute_public_key+0x34>
        return 0;
    }

    uECC_vli_nativeToBytes(public_key, curve->num_bytes, public);
 80064e2:	aa08      	add	r2, sp, #32
 80064e4:	f996 1001 	ldrsb.w	r1, [r6, #1]
 80064e8:	4638      	mov	r0, r7
 80064ea:	f7ff f9a6 	bl	800583a <uECC_vli_nativeToBytes>
    uECC_vli_nativeToBytes(
 80064ee:	f996 2000 	ldrsb.w	r2, [r6]
 80064f2:	f996 1001 	ldrsb.w	r1, [r6, #1]
 80064f6:	ab08      	add	r3, sp, #32
 80064f8:	1878      	adds	r0, r7, r1
 80064fa:	eb03 0282 	add.w	r2, r3, r2, lsl #2
 80064fe:	f7ff f99c 	bl	800583a <uECC_vli_nativeToBytes>
        public_key + curve->num_bytes, curve->num_bytes, public + curve->num_words);
    return 1;
 8006502:	4620      	mov	r0, r4
}
 8006504:	b019      	add	sp, #100	; 0x64
 8006506:	bdf0      	pop	{r4, r5, r6, r7, pc}

08006508 <uECC_verify>:

int uECC_verify(const uint8_t *public_key,
                const uint8_t *message_hash,
                unsigned hash_size,
                const uint8_t *signature,
                uECC_Curve curve) {
 8006508:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
 800650c:	b0fd      	sub	sp, #500	; 0x1f4
 800650e:	461d      	mov	r5, r3
 8006510:	9c86      	ldr	r4, [sp, #536]	; 0x218
 8006512:	9106      	str	r1, [sp, #24]
    const uECC_word_t *points[4];
    const uECC_word_t *point;
    bitcount_t num_bits;
    bitcount_t i;
    uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
 8006514:	7823      	ldrb	r3, [r4, #0]
 8006516:	9302      	str	r3, [sp, #8]
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 8006518:	f9b4 3002 	ldrsh.w	r3, [r4, #2]

int uECC_verify(const uint8_t *public_key,
                const uint8_t *message_hash,
                unsigned hash_size,
                const uint8_t *signature,
                uECC_Curve curve) {
 800651c:	9207      	str	r2, [sp, #28]
    const uECC_word_t *point;
    bitcount_t num_bits;
    bitcount_t i;
    uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 800651e:	331f      	adds	r3, #31
 8006520:	f04f 0a20 	mov.w	sl, #32
 8006524:	fb93 f3fa 	sdiv	r3, r3, sl
 8006528:	b2db      	uxtb	r3, r3
 800652a:	9304      	str	r3, [sp, #16]
    
    rx[num_n_words - 1] = 0;
 800652c:	f99d 7010 	ldrsb.w	r7, [sp, #16]
    r[num_n_words - 1] = 0;
    s[num_n_words - 1] = 0;

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
 8006530:	f994 2001 	ldrsb.w	r2, [r4, #1]
    bitcount_t i;
    uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    
    rx[num_n_words - 1] = 0;
 8006534:	f107 38ff 	add.w	r8, r7, #4294967295	; 0xffffffff
 8006538:	ab24      	add	r3, sp, #144	; 0x90
 800653a:	2600      	movs	r6, #0
 800653c:	f843 6028 	str.w	r6, [r3, r8, lsl #2]
    r[num_n_words - 1] = 0;
 8006540:	ab7c      	add	r3, sp, #496	; 0x1f0
 8006542:	eb03 0388 	add.w	r3, r3, r8, lsl #2
    s[num_n_words - 1] = 0;

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
 8006546:	4601      	mov	r1, r0

int uECC_verify(const uint8_t *public_key,
                const uint8_t *message_hash,
                unsigned hash_size,
                const uint8_t *signature,
                uECC_Curve curve) {
 8006548:	4681      	mov	r9, r0
    
    rx[num_n_words - 1] = 0;
    r[num_n_words - 1] = 0;
    s[num_n_words - 1] = 0;

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
 800654a:	a85c      	add	r0, sp, #368	; 0x170
    uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
    wordcount_t num_words = curve->num_words;
    wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    
    rx[num_n_words - 1] = 0;
    r[num_n_words - 1] = 0;
 800654c:	f843 6cc0 	str.w	r6, [r3, #-192]
    s[num_n_words - 1] = 0;
 8006550:	f843 6ca0 	str.w	r6, [r3, #-160]

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
 8006554:	f7ff f985 	bl	8005862 <uECC_vli_bytesToNative>
    uECC_vli_bytesToNative(
        public + num_words, public_key + curve->num_bytes, curve->num_bytes);
 8006558:	f99d b008 	ldrsb.w	fp, [sp, #8]
 800655c:	ea4f 038b 	mov.w	r3, fp, lsl #2
 8006560:	9303      	str	r3, [sp, #12]
    rx[num_n_words - 1] = 0;
    r[num_n_words - 1] = 0;
    s[num_n_words - 1] = 0;

    uECC_vli_bytesToNative(public, public_key, curve->num_bytes);
    uECC_vli_bytesToNative(
 8006562:	9a03      	ldr	r2, [sp, #12]
 8006564:	ab5c      	add	r3, sp, #368	; 0x170
 8006566:	4413      	add	r3, r2
 8006568:	f994 2001 	ldrsb.w	r2, [r4, #1]
 800656c:	9305      	str	r3, [sp, #20]
 800656e:	4618      	mov	r0, r3
 8006570:	eb09 0102 	add.w	r1, r9, r2
 8006574:	f7ff f975 	bl	8005862 <uECC_vli_bytesToNative>
        public + num_words, public_key + curve->num_bytes, curve->num_bytes);
    uECC_vli_bytesToNative(r, signature, curve->num_bytes);
 8006578:	4629      	mov	r1, r5
 800657a:	f994 2001 	ldrsb.w	r2, [r4, #1]
 800657e:	a84c      	add	r0, sp, #304	; 0x130
 8006580:	f7ff f96f 	bl	8005862 <uECC_vli_bytesToNative>
    uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
 8006584:	f994 2001 	ldrsb.w	r2, [r4, #1]
 8006588:	a854      	add	r0, sp, #336	; 0x150
 800658a:	18a9      	adds	r1, r5, r2
 800658c:	f7ff f969 	bl	8005862 <uECC_vli_bytesToNative>
    
    /* r, s must not be 0. */
    if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
 8006590:	4659      	mov	r1, fp
 8006592:	a84c      	add	r0, sp, #304	; 0x130
 8006594:	f7ff f807 	bl	80055a6 <uECC_vli_isZero>
 8006598:	4605      	mov	r5, r0
 800659a:	2800      	cmp	r0, #0
 800659c:	f040 8171 	bne.w	8006882 <uECC_verify+0x37a>
 80065a0:	4659      	mov	r1, fp
 80065a2:	a854      	add	r0, sp, #336	; 0x150
 80065a4:	f7fe ffff 	bl	80055a6 <uECC_vli_isZero>
 80065a8:	4606      	mov	r6, r0
 80065aa:	2800      	cmp	r0, #0
 80065ac:	f040 8167 	bne.w	800687e <uECC_verify+0x376>
        return 0;
    }

    /* r, s must be < n. */
    if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
 80065b0:	f104 0924 	add.w	r9, r4, #36	; 0x24
 80065b4:	463a      	mov	r2, r7
 80065b6:	a94c      	add	r1, sp, #304	; 0x130
 80065b8:	4648      	mov	r0, r9
 80065ba:	f7ff f83c 	bl	8005636 <uECC_vli_cmp_unsafe>
 80065be:	2801      	cmp	r0, #1
 80065c0:	f040 815f 	bne.w	8006882 <uECC_verify+0x37a>
            uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
 80065c4:	463a      	mov	r2, r7
 80065c6:	a954      	add	r1, sp, #336	; 0x150
 80065c8:	4648      	mov	r0, r9
 80065ca:	f7ff f834 	bl	8005636 <uECC_vli_cmp_unsafe>
    if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
        return 0;
    }

    /* r, s must be < n. */
    if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
 80065ce:	2801      	cmp	r0, #1
 80065d0:	f040 8157 	bne.w	8006882 <uECC_verify+0x37a>
            uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
        return 0;
    }

    /* Calculate u1 and u2. */
    uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
 80065d4:	ad1c      	add	r5, sp, #112	; 0x70
 80065d6:	463b      	mov	r3, r7
 80065d8:	464a      	mov	r2, r9
 80065da:	a954      	add	r1, sp, #336	; 0x150
 80065dc:	4628      	mov	r0, r5
 80065de:	f7ff fbac 	bl	8005d3a <uECC_vli_modInv>

static void bits2int(uECC_word_t *native,
                     const uint8_t *bits,
                     unsigned bits_size,
                     uECC_Curve curve) {
    unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
 80065e2:	f9b4 3002 	ldrsh.w	r3, [r4, #2]
        return 0;
    }

    /* Calculate u1 and u2. */
    uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
    u1[num_n_words - 1] = 0;
 80065e6:	af0c      	add	r7, sp, #48	; 0x30

static void bits2int(uECC_word_t *native,
                     const uint8_t *bits,
                     unsigned bits_size,
                     uECC_Curve curve) {
    unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
 80065e8:	1dda      	adds	r2, r3, #7
    unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
 80065ea:	331f      	adds	r3, #31
 80065ec:	fb93 fafa 	sdiv	sl, r3, sl
 80065f0:	9b07      	ldr	r3, [sp, #28]
        return 0;
    }

    /* Calculate u1 and u2. */
    uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
    u1[num_n_words - 1] = 0;
 80065f2:	f847 6028 	str.w	r6, [r7, r8, lsl #2]

static void bits2int(uECC_word_t *native,
                     const uint8_t *bits,
                     unsigned bits_size,
                     uECC_Curve curve) {
    unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
 80065f6:	f04f 0808 	mov.w	r8, #8
 80065fa:	fb92 f8f8 	sdiv	r8, r2, r8
 80065fe:	4543      	cmp	r3, r8
 8006600:	bf28      	it	cs
 8006602:	4643      	movcs	r3, r8
    unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
    if (bits_size > num_n_bytes) {
        bits_size = num_n_bytes;
    }
    uECC_vli_clear(native, num_n_words);
 8006604:	fa4f fb8a 	sxtb.w	fp, sl
 8006608:	4698      	mov	r8, r3
 800660a:	4659      	mov	r1, fp
 800660c:	4638      	mov	r0, r7
 800660e:	f7fe ffbe 	bl	800558e <uECC_vli_clear>
    uECC_vli_bytesToNative(native, bits, bits_size);
 8006612:	4642      	mov	r2, r8
 8006614:	9906      	ldr	r1, [sp, #24]
 8006616:	4638      	mov	r0, r7
 8006618:	f7ff f923 	bl	8005862 <uECC_vli_bytesToNative>
    if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
 800661c:	f9b4 3002 	ldrsh.w	r3, [r4, #2]
 8006620:	ea4f 08c8 	mov.w	r8, r8, lsl #3
 8006624:	4598      	cmp	r8, r3
 8006626:	d91d      	bls.n	8006664 <uECC_verify+0x15c>
        return;
    }
    int shift = bits_size * 8 - curve->num_n_bits;
 8006628:	ebc3 0808 	rsb	r8, r3, r8
 800662c:	eb07 0a8a 	add.w	sl, r7, sl, lsl #2
    uECC_word_t carry = 0;
    uECC_word_t *ptr = native + num_n_words;
    while (ptr-- > native) {
        uECC_word_t temp = *ptr;
        *ptr = (temp >> shift) | carry;
        carry = temp << (uECC_WORD_BITS - shift);
 8006630:	f1c8 0120 	rsb	r1, r8, #32
        return;
    }
    int shift = bits_size * 8 - curve->num_n_bits;
    uECC_word_t carry = 0;
    uECC_word_t *ptr = native + num_n_words;
    while (ptr-- > native) {
 8006634:	4557      	cmp	r7, sl
 8006636:	d209      	bcs.n	800664c <uECC_verify+0x144>
        uECC_word_t temp = *ptr;
 8006638:	f85a 2d04 	ldr.w	r2, [sl, #-4]!
        *ptr = (temp >> shift) | carry;
 800663c:	fa22 f308 	lsr.w	r3, r2, r8
 8006640:	431e      	orrs	r6, r3
 8006642:	f8ca 6000 	str.w	r6, [sl]
        carry = temp << (uECC_WORD_BITS - shift);
 8006646:	fa02 f601 	lsl.w	r6, r2, r1
 800664a:	e7f3      	b.n	8006634 <uECC_verify+0x12c>
    }

    /* Reduce mod curve_n */
    if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
 800664c:	465a      	mov	r2, fp
 800664e:	4639      	mov	r1, r7
 8006650:	4648      	mov	r0, r9
 8006652:	f7fe fff0 	bl	8005636 <uECC_vli_cmp_unsafe>
 8006656:	2801      	cmp	r0, #1
 8006658:	d004      	beq.n	8006664 <uECC_verify+0x15c>
        uECC_vli_sub(native, native, curve->n, num_n_words);
 800665a:	464a      	mov	r2, r9
 800665c:	4639      	mov	r1, r7
 800665e:	4638      	mov	r0, r7
 8006660:	f7ff f9c9 	bl	80059f6 <uECC_vli_sub.isra.1>

    /* Calculate u1 and u2. */
    uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
    u1[num_n_words - 1] = 0;
    bits2int(u1, message_hash, hash_size, curve);
    uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
 8006664:	f99d 8010 	ldrsb.w	r8, [sp, #16]
 8006668:	f8cd 8000 	str.w	r8, [sp]
 800666c:	4639      	mov	r1, r7
 800666e:	4638      	mov	r0, r7
 8006670:	464b      	mov	r3, r9
 8006672:	462a      	mov	r2, r5
 8006674:	f7ff f802 	bl	800567c <uECC_vli_modMult>
    uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
 8006678:	464b      	mov	r3, r9
 800667a:	f8cd 8000 	str.w	r8, [sp]
 800667e:	462a      	mov	r2, r5
 8006680:	a94c      	add	r1, sp, #304	; 0x130
 8006682:	a814      	add	r0, sp, #80	; 0x50
 8006684:	f7fe fffa 	bl	800567c <uECC_vli_modMult>
    
    /* Calculate sum = G + Q. */
    uECC_vli_set(sum, public, num_words);
 8006688:	f99d a008 	ldrsb.w	sl, [sp, #8]
 800668c:	ae6c      	add	r6, sp, #432	; 0x1b0
 800668e:	4652      	mov	r2, sl
 8006690:	4630      	mov	r0, r6
 8006692:	a95c      	add	r1, sp, #368	; 0x170
 8006694:	f7fe ffc2 	bl	800561c <uECC_vli_set>
    uECC_vli_set(sum + num_words, public + num_words, num_words);
 8006698:	9b03      	ldr	r3, [sp, #12]
 800669a:	9905      	ldr	r1, [sp, #20]
 800669c:	eb06 0b03 	add.w	fp, r6, r3
 80066a0:	4652      	mov	r2, sl
 80066a2:	4658      	mov	r0, fp
 80066a4:	f7fe ffba 	bl	800561c <uECC_vli_set>
    uECC_vli_set(tx, curve->G, num_words);
 80066a8:	f104 0344 	add.w	r3, r4, #68	; 0x44
 80066ac:	4652      	mov	r2, sl
 80066ae:	4619      	mov	r1, r3
 80066b0:	a834      	add	r0, sp, #208	; 0xd0
 80066b2:	9305      	str	r3, [sp, #20]
 80066b4:	f7fe ffb2 	bl	800561c <uECC_vli_set>
    uECC_vli_set(ty, curve->G + num_words, num_words);
 80066b8:	9b05      	ldr	r3, [sp, #20]
 80066ba:	9903      	ldr	r1, [sp, #12]
 80066bc:	4652      	mov	r2, sl
 80066be:	1859      	adds	r1, r3, r1
 80066c0:	a83c      	add	r0, sp, #240	; 0xf0
 80066c2:	f7fe ffab 	bl	800561c <uECC_vli_set>
    uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
 80066c6:	1d23      	adds	r3, r4, #4
 80066c8:	4631      	mov	r1, r6
 80066ca:	aa34      	add	r2, sp, #208	; 0xd0
 80066cc:	4628      	mov	r0, r5
 80066ce:	9306      	str	r3, [sp, #24]
 80066d0:	f7ff fa24 	bl	8005b1c <uECC_vli_modSub.isra.2>
    XYcZ_add(tx, ty, sum, sum + num_words, curve);
 80066d4:	465b      	mov	r3, fp
 80066d6:	4632      	mov	r2, r6
 80066d8:	a93c      	add	r1, sp, #240	; 0xf0
 80066da:	a834      	add	r0, sp, #208	; 0xd0
 80066dc:	9400      	str	r4, [sp, #0]
 80066de:	f7ff fa2b 	bl	8005b38 <XYcZ_add>
    uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
 80066e2:	4653      	mov	r3, sl
 80066e4:	1d22      	adds	r2, r4, #4
 80066e6:	4629      	mov	r1, r5
 80066e8:	4628      	mov	r0, r5
 80066ea:	f7ff fb26 	bl	8005d3a <uECC_vli_modInv>
    apply_z(sum, sum + num_words, z, curve);
 80066ee:	462a      	mov	r2, r5
 80066f0:	4659      	mov	r1, fp
 80066f2:	4630      	mov	r0, r6
 80066f4:	4623      	mov	r3, r4
 80066f6:	f7ff f881 	bl	80057fc <apply_z>
    
    /* Use Shamir's trick to calculate u1*G + u2*Q */
    points[0] = 0;
 80066fa:	2300      	movs	r3, #0
 80066fc:	9308      	str	r3, [sp, #32]
    points[1] = curve->G;
 80066fe:	9b05      	ldr	r3, [sp, #20]
 8006700:	9309      	str	r3, [sp, #36]	; 0x24
    points[2] = public;
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
 8006702:	4641      	mov	r1, r8
    apply_z(sum, sum + num_words, z, curve);
    
    /* Use Shamir's trick to calculate u1*G + u2*Q */
    points[0] = 0;
    points[1] = curve->G;
    points[2] = public;
 8006704:	ab5c      	add	r3, sp, #368	; 0x170
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
 8006706:	4638      	mov	r0, r7
    apply_z(sum, sum + num_words, z, curve);
    
    /* Use Shamir's trick to calculate u1*G + u2*Q */
    points[0] = 0;
    points[1] = curve->G;
    points[2] = public;
 8006708:	930a      	str	r3, [sp, #40]	; 0x28
    points[3] = sum;
 800670a:	960b      	str	r6, [sp, #44]	; 0x2c
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
 800670c:	f7fe ff64 	bl	80055d8 <uECC_vli_numBits>
 8006710:	4641      	mov	r1, r8
 8006712:	4606      	mov	r6, r0
 8006714:	a814      	add	r0, sp, #80	; 0x50
 8006716:	f7fe ff5f 	bl	80055d8 <uECC_vli_numBits>
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
 800671a:	42b0      	cmp	r0, r6
 800671c:	bfb8      	it	lt
 800671e:	4630      	movlt	r0, r6
 8006720:	b286      	uxth	r6, r0
 8006722:	f106 38ff 	add.w	r8, r6, #4294967295	; 0xffffffff
 8006726:	fa0f f888 	sxth.w	r8, r8
 800672a:	4641      	mov	r1, r8
 800672c:	4638      	mov	r0, r7
 800672e:	f7fe ff49 	bl	80055c4 <uECC_vli_testBit>
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
 8006732:	4641      	mov	r1, r8
    points[2] = public;
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
 8006734:	1c07      	adds	r7, r0, #0
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
 8006736:	a814      	add	r0, sp, #80	; 0x50
    points[2] = public;
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
 8006738:	bf18      	it	ne
 800673a:	2701      	movne	r7, #1
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
 800673c:	f7fe ff42 	bl	80055c4 <uECC_vli_testBit>
 8006740:	2800      	cmp	r0, #0
 8006742:	bf14      	ite	ne
 8006744:	2302      	movne	r3, #2
 8006746:	2300      	moveq	r3, #0
    points[2] = public;
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
 8006748:	431f      	orrs	r7, r3
    XYcZ_add(tx, ty, sum, sum + num_words, curve);
    uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
    apply_z(sum, sum + num_words, z, curve);
    
    /* Use Shamir's trick to calculate u1*G + u2*Q */
    points[0] = 0;
 800674a:	f10d 0b20 	add.w	fp, sp, #32
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
    uECC_vli_set(rx, point, num_words);
 800674e:	f10d 0890 	add.w	r8, sp, #144	; 0x90
    points[2] = public;
    points[3] = sum;
    num_bits = smax(uECC_vli_numBits(u1, num_n_words),
                    uECC_vli_numBits(u2, num_n_words));
    
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
 8006752:	f85b b027 	ldr.w	fp, [fp, r7, lsl #2]
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
    uECC_vli_set(rx, point, num_words);
 8006756:	4652      	mov	r2, sl
 8006758:	4659      	mov	r1, fp
 800675a:	4640      	mov	r0, r8
 800675c:	f7fe ff5e 	bl	800561c <uECC_vli_set>
    uECC_vli_set(ry, point + num_words, num_words);
 8006760:	9b03      	ldr	r3, [sp, #12]
 8006762:	af2c      	add	r7, sp, #176	; 0xb0
 8006764:	eb0b 0103 	add.w	r1, fp, r3
 8006768:	4652      	mov	r2, sl
 800676a:	4638      	mov	r0, r7
 800676c:	f7fe ff56 	bl	800561c <uECC_vli_set>
    uECC_vli_clear(z, num_words);
 8006770:	4651      	mov	r1, sl
 8006772:	4628      	mov	r0, r5
 8006774:	f7fe ff0b 	bl	800558e <uECC_vli_clear>
    z[0] = 1;

    for (i = num_bits - 2; i >= 0; --i) {
 8006778:	3e02      	subs	r6, #2
    point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
                   ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
    uECC_vli_set(rx, point, num_words);
    uECC_vli_set(ry, point + num_words, num_words);
    uECC_vli_clear(z, num_words);
    z[0] = 1;
 800677a:	2301      	movs	r3, #1
 800677c:	602b      	str	r3, [r5, #0]

    for (i = num_bits - 2; i >= 0; --i) {
 800677e:	b2b6      	uxth	r6, r6
 8006780:	46ba      	mov	sl, r7
 8006782:	fa0f fb86 	sxth.w	fp, r6
 8006786:	f1bb 0f00 	cmp.w	fp, #0
 800678a:	db46      	blt.n	800681a <uECC_verify+0x312>
        uECC_word_t index;
        curve->double_jacobian(rx, ry, z, curve);
 800678c:	4623      	mov	r3, r4
 800678e:	462a      	mov	r2, r5
 8006790:	f8d4 70a4 	ldr.w	r7, [r4, #164]	; 0xa4
 8006794:	4651      	mov	r1, sl
 8006796:	4640      	mov	r0, r8
 8006798:	47b8      	blx	r7
        
        index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
 800679a:	4659      	mov	r1, fp
 800679c:	a80c      	add	r0, sp, #48	; 0x30
 800679e:	f7fe ff11 	bl	80055c4 <uECC_vli_testBit>
 80067a2:	4659      	mov	r1, fp
 80067a4:	1c07      	adds	r7, r0, #0
 80067a6:	a814      	add	r0, sp, #80	; 0x50
 80067a8:	bf18      	it	ne
 80067aa:	2701      	movne	r7, #1
 80067ac:	f7fe ff0a 	bl	80055c4 <uECC_vli_testBit>
 80067b0:	2800      	cmp	r0, #0
 80067b2:	bf14      	ite	ne
 80067b4:	2302      	movne	r3, #2
 80067b6:	2300      	moveq	r3, #0
        point = points[index];
 80067b8:	431f      	orrs	r7, r3
 80067ba:	ab08      	add	r3, sp, #32
 80067bc:	f853 b027 	ldr.w	fp, [r3, r7, lsl #2]
        if (point) {
 80067c0:	f1bb 0f00 	cmp.w	fp, #0
 80067c4:	d026      	beq.n	8006814 <uECC_verify+0x30c>
            uECC_vli_set(tx, point, num_words);
 80067c6:	f99d 7008 	ldrsb.w	r7, [sp, #8]
 80067ca:	4659      	mov	r1, fp
 80067cc:	463a      	mov	r2, r7
 80067ce:	a834      	add	r0, sp, #208	; 0xd0
 80067d0:	f7fe ff24 	bl	800561c <uECC_vli_set>
            uECC_vli_set(ty, point + num_words, num_words);
 80067d4:	9b03      	ldr	r3, [sp, #12]
 80067d6:	463a      	mov	r2, r7
 80067d8:	eb0b 0103 	add.w	r1, fp, r3
 80067dc:	a83c      	add	r0, sp, #240	; 0xf0
 80067de:	f7fe ff1d 	bl	800561c <uECC_vli_set>
            apply_z(tx, ty, z, curve);
 80067e2:	4623      	mov	r3, r4
 80067e4:	462a      	mov	r2, r5
 80067e6:	a93c      	add	r1, sp, #240	; 0xf0
 80067e8:	a834      	add	r0, sp, #208	; 0xd0
 80067ea:	f7ff f807 	bl	80057fc <apply_z>
            uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
 80067ee:	9b06      	ldr	r3, [sp, #24]
 80067f0:	aa34      	add	r2, sp, #208	; 0xd0
 80067f2:	4641      	mov	r1, r8
 80067f4:	a844      	add	r0, sp, #272	; 0x110
 80067f6:	f7ff f991 	bl	8005b1c <uECC_vli_modSub.isra.2>
            XYcZ_add(tx, ty, rx, ry, curve);
 80067fa:	4653      	mov	r3, sl
 80067fc:	4642      	mov	r2, r8
 80067fe:	a93c      	add	r1, sp, #240	; 0xf0
 8006800:	a834      	add	r0, sp, #208	; 0xd0
 8006802:	9400      	str	r4, [sp, #0]
 8006804:	f7ff f998 	bl	8005b38 <XYcZ_add>
            uECC_vli_modMult_fast(z, z, tz, curve);
 8006808:	4623      	mov	r3, r4
 800680a:	aa44      	add	r2, sp, #272	; 0x110
 800680c:	4629      	mov	r1, r5
 800680e:	4628      	mov	r0, r5
 8006810:	f7fe ffe0 	bl	80057d4 <uECC_vli_modMult_fast>
 8006814:	3e01      	subs	r6, #1
 8006816:	b2b6      	uxth	r6, r6
 8006818:	e7b3      	b.n	8006782 <uECC_verify+0x27a>
        }
    }

    uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
 800681a:	f99d 3008 	ldrsb.w	r3, [sp, #8]
 800681e:	9a06      	ldr	r2, [sp, #24]
 8006820:	4629      	mov	r1, r5
 8006822:	4628      	mov	r0, r5
 8006824:	f7ff fa89 	bl	8005d3a <uECC_vli_modInv>
    apply_z(rx, ry, z, curve);
 8006828:	4623      	mov	r3, r4
 800682a:	462a      	mov	r2, r5
 800682c:	4651      	mov	r1, sl
 800682e:	4640      	mov	r0, r8
 8006830:	f7fe ffe4 	bl	80057fc <apply_z>
    
    /* v = x1 (mod n) */
    if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
 8006834:	f99d 2010 	ldrsb.w	r2, [sp, #16]
 8006838:	4641      	mov	r1, r8
 800683a:	4648      	mov	r0, r9
 800683c:	f7fe fefb 	bl	8005636 <uECC_vli_cmp_unsafe>
 8006840:	2801      	cmp	r0, #1
 8006842:	d004      	beq.n	800684e <uECC_verify+0x346>
        uECC_vli_sub(rx, rx, curve->n, num_n_words);
 8006844:	464a      	mov	r2, r9
 8006846:	4641      	mov	r1, r8
 8006848:	4640      	mov	r0, r8
 800684a:	f7ff f8d4 	bl	80059f6 <uECC_vli_sub.isra.1>
uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
                                        const uECC_word_t *right,
                                        wordcount_t num_words) {
    uECC_word_t diff = 0;
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
 800684e:	9b02      	ldr	r3, [sp, #8]
 8006850:	3b01      	subs	r3, #1
 8006852:	b2db      	uxtb	r3, r3
/* Constant-time comparison function - secure way to compare long integers */
/* Returns one if left == right, zero otherwise. */
uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left,
                                        const uECC_word_t *right,
                                        wordcount_t num_words) {
    uECC_word_t diff = 0;
 8006854:	2600      	movs	r6, #0
    wordcount_t i;
    for (i = num_words - 1; i >= 0; --i) {
 8006856:	b25a      	sxtb	r2, r3
 8006858:	2a00      	cmp	r2, #0
 800685a:	db0c      	blt.n	8006876 <uECC_verify+0x36e>
        diff |= (left[i] ^ right[i]);
 800685c:	b212      	sxth	r2, r2
 800685e:	a97c      	add	r1, sp, #496	; 0x1f0
 8006860:	eb01 0082 	add.w	r0, r1, r2, lsl #2
 8006864:	f858 1022 	ldr.w	r1, [r8, r2, lsl #2]
 8006868:	f850 2cc0 	ldr.w	r2, [r0, #-192]
 800686c:	3b01      	subs	r3, #1
 800686e:	404a      	eors	r2, r1
 8006870:	4316      	orrs	r6, r2
 8006872:	b2db      	uxtb	r3, r3
 8006874:	e7ef      	b.n	8006856 <uECC_verify+0x34e>
    if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
        uECC_vli_sub(rx, rx, curve->n, num_n_words);
    }

    /* Accept only if v == r. */
    return (int)(uECC_vli_equal(rx, r, num_words));
 8006876:	fab6 f086 	clz	r0, r6
 800687a:	0940      	lsrs	r0, r0, #5
 800687c:	e002      	b.n	8006884 <uECC_verify+0x37c>
    uECC_vli_bytesToNative(r, signature, curve->num_bytes);
    uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
    
    /* r, s must not be 0. */
    if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
        return 0;
 800687e:	4628      	mov	r0, r5
 8006880:	e000      	b.n	8006884 <uECC_verify+0x37c>
 8006882:	4630      	mov	r0, r6
        uECC_vli_sub(rx, rx, curve->n, num_n_words);
    }

    /* Accept only if v == r. */
    return (int)(uECC_vli_equal(rx, r, num_words));
}
 8006884:	b07d      	add	sp, #500	; 0x1f4
 8006886:	e8bd 8ff0 	ldmia.w	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}

0800688a <memcmp>:
 800688a:	b510      	push	{r4, lr}
 800688c:	3901      	subs	r1, #1
 800688e:	4402      	add	r2, r0
 8006890:	4290      	cmp	r0, r2
 8006892:	d007      	beq.n	80068a4 <memcmp+0x1a>
 8006894:	f810 3b01 	ldrb.w	r3, [r0], #1
 8006898:	f811 4f01 	ldrb.w	r4, [r1, #1]!
 800689c:	42a3      	cmp	r3, r4
 800689e:	d0f7      	beq.n	8006890 <memcmp+0x6>
 80068a0:	1b18      	subs	r0, r3, r4
 80068a2:	bd10      	pop	{r4, pc}
 80068a4:	2000      	movs	r0, #0
 80068a6:	bd10      	pop	{r4, pc}

080068a8 <memcpy>:
 80068a8:	b510      	push	{r4, lr}
 80068aa:	1e43      	subs	r3, r0, #1
 80068ac:	440a      	add	r2, r1
 80068ae:	4291      	cmp	r1, r2
 80068b0:	d004      	beq.n	80068bc <memcpy+0x14>
 80068b2:	f811 4b01 	ldrb.w	r4, [r1], #1
 80068b6:	f803 4f01 	strb.w	r4, [r3, #1]!
 80068ba:	e7f8      	b.n	80068ae <memcpy+0x6>
 80068bc:	bd10      	pop	{r4, pc}

080068be <memmove>:
 80068be:	4288      	cmp	r0, r1
 80068c0:	b510      	push	{r4, lr}
 80068c2:	eb01 0302 	add.w	r3, r1, r2
 80068c6:	d801      	bhi.n	80068cc <memmove+0xe>
 80068c8:	1e42      	subs	r2, r0, #1
 80068ca:	e00b      	b.n	80068e4 <memmove+0x26>
 80068cc:	4298      	cmp	r0, r3
 80068ce:	d2fb      	bcs.n	80068c8 <memmove+0xa>
 80068d0:	1881      	adds	r1, r0, r2
 80068d2:	1ad2      	subs	r2, r2, r3
 80068d4:	42d3      	cmn	r3, r2
 80068d6:	d004      	beq.n	80068e2 <memmove+0x24>
 80068d8:	f813 4d01 	ldrb.w	r4, [r3, #-1]!
 80068dc:	f801 4d01 	strb.w	r4, [r1, #-1]!
 80068e0:	e7f8      	b.n	80068d4 <memmove+0x16>
 80068e2:	bd10      	pop	{r4, pc}
 80068e4:	4299      	cmp	r1, r3
 80068e6:	d004      	beq.n	80068f2 <memmove+0x34>
 80068e8:	f811 4b01 	ldrb.w	r4, [r1], #1
 80068ec:	f802 4f01 	strb.w	r4, [r2, #1]!
 80068f0:	e7f8      	b.n	80068e4 <memmove+0x26>
 80068f2:	bd10      	pop	{r4, pc}

080068f4 <memset>:
 80068f4:	4402      	add	r2, r0
 80068f6:	4603      	mov	r3, r0
 80068f8:	4293      	cmp	r3, r2
 80068fa:	d002      	beq.n	8006902 <memset+0xe>
 80068fc:	f803 1b01 	strb.w	r1, [r3], #1
 8006900:	e7fa      	b.n	80068f8 <memset+0x4>
 8006902:	4770      	bx	lr

08006904 <strlcpy>:
 8006904:	b510      	push	{r4, lr}
 8006906:	460b      	mov	r3, r1
 8006908:	b152      	cbz	r2, 8006920 <strlcpy+0x1c>
 800690a:	3a01      	subs	r2, #1
 800690c:	d006      	beq.n	800691c <strlcpy+0x18>
 800690e:	f813 4b01 	ldrb.w	r4, [r3], #1
 8006912:	f800 4b01 	strb.w	r4, [r0], #1
 8006916:	2c00      	cmp	r4, #0
 8006918:	d1f7      	bne.n	800690a <strlcpy+0x6>
 800691a:	e005      	b.n	8006928 <strlcpy+0x24>
 800691c:	2200      	movs	r2, #0
 800691e:	7002      	strb	r2, [r0, #0]
 8006920:	f813 2b01 	ldrb.w	r2, [r3], #1
 8006924:	2a00      	cmp	r2, #0
 8006926:	d1fb      	bne.n	8006920 <strlcpy+0x1c>
 8006928:	1a58      	subs	r0, r3, r1
 800692a:	3801      	subs	r0, #1
 800692c:	bd10      	pop	{r4, pc}

0800692e <strlen>:
 800692e:	4603      	mov	r3, r0
 8006930:	f813 2b01 	ldrb.w	r2, [r3], #1
 8006934:	2a00      	cmp	r2, #0
 8006936:	d1fb      	bne.n	8006930 <strlen+0x2>
 8006938:	1a18      	subs	r0, r3, r0
 800693a:	3801      	subs	r0, #1
 800693c:	4770      	bx	lr
	...

08006940 <__flash_burn_veneer>:
 8006940:	b401      	push	{r0}
 8006942:	4802      	ldr	r0, [pc, #8]	; (800694c <__flash_burn_veneer+0xc>)
 8006944:	4684      	mov	ip, r0
 8006946:	bc01      	pop	{r0}
 8006948:	4760      	bx	ip
 800694a:	bf00      	nop
 800694c:	10006001 	.word	0x10006001

08006950 <__flash_page_erase_veneer>:
 8006950:	b401      	push	{r0}
 8006952:	4802      	ldr	r0, [pc, #8]	; (800695c <__flash_page_erase_veneer+0xc>)
 8006954:	4684      	mov	ip, r0
 8006956:	bc01      	pop	{r0}
 8006958:	4760      	bx	ip
 800695a:	bf00      	nop
 800695c:	10006105 	.word	0x10006105
 8006960:	65737361 	.word	0x65737361
 8006964:	42007472 	.word	0x42007472
 8006968:	32746f6f 	.word	0x32746f6f
 800696c:	00554644 	.word	0x00554644

08006970 <AHBPrescTable>:
	...
 8006978:	04030201 09080706                       ........

08006980 <APBPrescTable>:
 8006980:	00000000 04030201                       ........

08006988 <MSIRangeTable>:
 8006988:	000186a0 00030d40 00061a80 000c3500     ....@........5..
 8006998:	000f4240 001e8480 003d0900 007a1200     @B........=...z.
 80069a8:	00f42400 016e3600 01e84800 02dc6c00     .$...6n..H...l..
 80069b8:	00000150 00000001 00000000 00000001     P...............
 80069c8:	00000000                                ....

080069cc <before_show>:
 80069cc:	227f0021 20ae0700                                !.."..

080069d2 <reset_commands>:
 80069d2:	400020ae c83fa8a1 12da00d3 f1d980d5     . .@..?.........
 80069e2:	ff8130db 148da6a4 35007faf                       .0.......

080069eb <screen_logout>:
 80069eb:	0035007f c0078081 00064081 6f808082     ..5......@.....o
 80069fb:	ffff8200 c0070006 c7c3c189 f0f8dcce     ................
 8006a0b:	0068c0e0 07ff7f82 88000680 1c387060     ..h.........`p8.
 8006a1b:	0103070e 0050007f 0006f881 40048081     ......P........@
 8006a2b:	80008083 80844003 048000c0 00808340     .....@......@...
 8006a3b:	840004c0 f04000c0 00094003 0803f881     ......@..@......
 8006a4b:	00e01084 84400480 80c00080 80834003     ......@......@..
 8006a5b:	40048000 00348081 10051f81 040f0082     ...@..4.........
 8006a6b:	000f8310 84880347 0f007f84 0f831004     ....G...........
 8006a7b:	10030f00 001f0885 10030f00 00080881     ................
 8006a8b:	10031f81 00070884 8310040f 041f000f     ................
 8006a9b:	001f8300 8112040f 1b007f13 007f0000              ..............

08006aa9 <screen_blank>:
 8006aa9:	007f007f 0034007f 000d8081 000d8081     ......4.........
 8006ab9:	00628081 01030183 0183000b 000b0103     ..b.............
 8006ac9:	01030183 007f007f 0034007f 38007f00              ..........4..

08006ad6 <screen_verify>:
 8006ad6:	0038007f 60c0808a 10303060 03181810     ..8....``00.....
 8006ae6:	20308510 6b80c060 fce08400 0007030f     ..0 `..k........
 8006af6:	07ffff82 07018400 0068e0fc 3c0f0187     ..........h....<
 8006b06:	8080c060 018c0005 00060703 70c08080     `..............p
 8006b16:	6d010f38 01018e00 02020303 02020606     8..m............
 8006b26:	01010303 f881005a f8830004 40048000     ....Z..........@
 8006b36:	c0008084 86400380 40000080 0004d840     ......@....@@...
 8006b46:	0803f081 c0001083 c0860004 40400000     ..............@@
 8006b56:	820003d8 400380c0 80008083 80824003     .......@.....@..
 8006b66:	880042c0 18180601 0f000106 13831204     .B..............
 8006b76:	00091f00 00031f81 031f0182 00008301     ................
 8006b86:	82880347 00047f84 00031f81 00041f81     G...............
 8006b96:	47001f83 84828803 22007f7f 007f0000              ...G......."..

08006ba4 <screen_upgrading>:
 8006ba4:	0035007f 0e80c082 6a800600 ffff8200     ..5........j....
 8006bb4:	80900005 603060c0 63c080c0 30181c37     .....`0`...c7..0
 8006bc4:	691f3f20 ffff8800 8e8c8080 80058183      ?.i............
 8006bd4:	800a8181 0056007f 0004f881 c000f884     ......V.........
 8006be4:	83400380 03800080 c0808540 0380c000     ..@.....@.......
 8006bf4:	00808340 83400400 03800080 f8808740     @.....@.....@...
 8006c04:	40400000 820003d8 400380c0 80008083     ..@@.......@....
 8006c14:	80824003 810042c0 8410040f 047f000f     .@...B..........
 8006c24:	07830803 88034700 007f8484 8100061f     .....G..........
 8006c34:	8411030e 0f001f09 08821003 8100041f     ................
 8006c44:	8100031f 8300041f 0347001f 7f848288     ..........G.....
 8006c54:	0022007f 7f007f00                                .."..

08006c59 <screen_fatal>:
 8006c59:	007f007f 002b007f 40f04089 0040f040     ......+..@.@@.@.
 8006c69:	0803f000 c0001083 c0840004 03f00000     ................
 8006c79:	00108308 86400400 40000080 0004d840     ......@....@@...
 8006c89:	0054f881 020f0289 00020f02 01031f01     ..T.............
 8006c99:	0f00008b 100f0810 1f01000f 00830103     ................
 8006ca9:	11030e00 041f0982 041f8100 030f8100     ................
 8006cb9:	7f007f10 2c007f00 007f0000                       .......,..

08006cc3 <screen_dfu>:
 8006cc3:	007f007f 0039007f 0803f881 00e01084     ......9.........
 8006cd3:	838804f8 04f80008 6cf88100 031f8100     ...........l....
 8006ce3:	07088410 00061f00 10040f81 007f0f81     ................
 8006cf3:	007f007f 7f000039                                ....9..

08006cfa <screen_replug>:
 8006cfa:	007f007f 002f007f 0804f881 8000f083     ....../.........
 8006d0a:	80844004 0380c000 00808440 0005f800     .@......@.......
 8006d1a:	0004c081 8000c083 80824003 880057c0     .........@...W..
 8006d2a:	0503011f 0f001009 13841204 03047f00     ................
 8006d3a:	00078408 10030f00 0f000083 08841003     ................
 8006d4a:	0347001f 7f848288 007f007f 002e007f     ..G.............
	...

08006d5b <screen_brick>:
 8006d5b:	007f007f 002b007f 8803f881 0000f085     ......+.........
 8006d6b:	400380c0 00008086 03d84040 04808100     ...@....@@......
 8006d7b:	00808a40 800000f8 80000040 80834004     @.......@....@..
 8006d8b:	40038000 50f88082 041f8100 000f8310     ...@...P........
 8006d9b:	8100091f 8100031f 8a10040f 021f0008     ................
 8006dab:	10080403 12040f00 0f001383 08821003     ................
 8006dbb:	7f007f1f 2b007f00 007f0000                       .......+..

08006dc5 <screen_devmode>:
 8006dc5:	002e007f 00888003 98f09000 1540d0a0     ..............@.
 8006dd5:	80808400 180330e0 18031081 80e03084     .....0.......0..
 8006de5:	89004480 0c18f0c0 191373e6 89010519     .D.......s......
 8006df5:	07030100 000039ef 92001401 f9cdc702     .....9..........
 8006e05:	783818c8 78381838 f9c81838 0043e7ed     ..8x8.8x8.....C.
 8006e15:	e03f0f85 000a0180 70c08085 0016023f     ..?........p?...
 8006e25:	07fcf883 7e870304 640464fc 03047efc     .......~.d.d.~..
 8006e35:	f0fc0783 01840044 06020301 03028306     ....D...........
 8006e45:	82001a01 04060703 04030781 04060781     ................
 8006e55:	2a030782 03f88100 e0108408 40040000     ...*...........@
 8006e65:	c0008084 83400380 03800080 c0808440     ......@.....@...
 8006e75:	40048000 c0008084 81400380 81000380     ...@......@.....
 8006e85:	81000bf8 830804f0 04000030 00808340     ........0...@...
 8006e95:	840004c0 f04000c0 00034003 d8404083     ......@..@...@@.
 8006ea5:	80810003 80844004 0380c000 03808140     .....@......@...
 8006eb5:	14f88100 031f8100 07088410 11030e00     ................
 8006ec5:	001f0984 8300041f 0347001f 7f848488     ..........G.....
 8006ed5:	12040f00 1f001383 1b810008 0f81000b     ................
 8006ee5:	0c831004 11030e00 001f0984 8510030f     ................
 8006ef5:	00001f08 8110030f 81000408 8100031f     ................
 8006f05:	8310040f 041f000f 031f8100 7f1b8100     ................
 8006f15:	00000c00                                ....

08006f19 <screen_downgrade>:
 8006f19:	0035007f 00f0f095 6060c080 10103030     ..5.......``00..
 8006f29:	10101818 60603030 006b80c0 0c040f04     ....00``..k.....
 8006f39:	ff820003 840007ff e0fc0f03 c083006c     ............l...
 8006f49:	00058080 0603018c 80800006 0f3c70c0     .............p<.
 8006f59:	8e006d01 03030101 06060202 03030202     .m..............
 8006f69:	00570101 0803f881 00e01084 83400480     ..W...........@.
 8006f79:	04c00080 00c08400 400380c0 80008083     ...........@....
 8006f89:	80854003 80c000c0 80834003 40040000     .@.......@.....@
 8006f99:	80008083 80844003 048000f8 00808740     .....@......@...
 8006fa9:	48880808 81003c30 8410031f 0f000708     ...H0<..........
 8006fb9:	0f8a1004 08100f00 000f100f 8300041f     ................
 8006fc9:	0347001f 7f848488 00061f00 11030e81     ..G.............
 8006fd9:	001f0984 8410030f 0f001f08 13841204     ................
 8006fe9:	7f1b0000 00002200                       ....."..

08006ff1 <screen_corrupt>:
 8006ff1:	0039007f c0808085 20036060 20053081     ..9.....``. .0. 
 8007001:	30103085 0069c060 0e38f08c 0c1871c3     .0.0`.i...8..q..
 8007011:	01030206 82000901 0068c1ff 00ff8285     ..........h.....
 8007021:	000d0100 70c08085 00690f3c 0c070385     .......p<.i.....
 8007031:	04050c08 04030c81 03060685 005b0101     ..............[.
 8007041:	8804f881 00000886 03d84040 80c08200     ........@@......
 8007051:	808a4003 4040c000 00804080 830004c0     .@....@@.@......
 8007061:	040000c0 00808440 400380c0 80008083     ....@......@....
 8007071:	80874004 88080800 00433048 00091f81     .@......H0C.....
 8007081:	00031f81 00061f81 00001f8f 001f0007     ................
 8007091:	0f08100f 0e000f10 09841103 061f001f     ................
 80070a1:	040f8100 00138412 007f1b00 b4000026              ............&..

080070b0 <approved_pubkeys>:
 80070b0:	2641cbb4 f36ce1f7 71b4f28f 0123fb1d     ..A&..l....q..#.
 80070c0:	66d6760d 6ca38aa7 f6f9539b 0518587b     .v.f...l.S..{X..
 80070d0:	e93b0b58 b89fc431 113c0444 470f0896     X.;.1...D.<....G
 80070e0:	37ed2581 4a9e237a 3818b7af da0438ba     .%.7z#.J...8.8..
 80070f0:	1dc8a2d6 df5e811c 6d290ca6 8d8f57b8     ......^...)m.W..
 8007100:	9269295e c178d1ce 31d7207b b596a17b     ^)i...x.{ .1{...
 8007110:	0c1bef3d c31a79aa c8c45845 ffeb2d8a     =....y..EX...-..
 8007120:	01829bfe bc5e5f87 4fe5a596 9ffe68c7     ....._^....O.h..
 8007130:	0166ef42 95cfc456 38f0b5f4 c5261164     B.f.V......8d.&.
 8007140:	66c13999 14120632 689c254c bad38c35     .9.f2...L%.h5...
 8007150:	8cde7824 6cdfab52 7809bfb8 3a63bb03     $x..R..l...x..c:
 8007160:	0ed90111 8f737aa4 7f3b18bf c87b0af0     .....zs...;...{.
 8007170:	56546067 c5ec0c82 0882bc1d ef39c116     g`TV..........9.
 8007180:	32babff5 e35fce7c d7621e74 4cc5fce9     ...2|._.t.b....L
 8007190:	8d11e88a 13c2adc3 2a4f2992 a4f8d2ea     .........)O*....
 80071a0:	fe7cd5c4 3b450512 07598954 88d7d6da     ..|...E;T.Y.....
 80071b0:	37cfb143 1f897cd2 f3acfe5b 95fc33ba     C..7.|..[....3..
 80071c0:	dde7d981 14ef9525 bb97efdd a7d8f333     ....%.......3...
 80071d0:	977a2b34 73aab3ba 32419de7 17a1fcd8     4+z....s..A2....
 80071e0:	fe0bb566 89214063 8e7b92c9 590bdf72     f...c@!...{.r..Y
	...
 8007230:	6f636e69 2301006e                       incon..#

08007238 <CSWTCH.54>:
 8007238:	64640103 0e646464 64646464 64646464     ..ddddd.dddddddd
 8007248:	64641a17 64201e0b 32176464 0a646464     ..dd.. ddd.2ddd.
 8007258:	14646464 0d646464 64646464 02646464     ddd.ddd.ddddddd.
 8007268:	64646464 64646464 64646464 73646464     ddddddddddddddds
 8007278:	643a6432 e109303a                                2d:d:0.

0800727f <config_1.8468>:
 800727f:	005500e1 2d8f0000 438f808f 4300448f     ..U....-...C.D.C
 800728f:	478f4400 43c3488f 47c744c4 4d8f48c8     .D.G.H.C.D.G.H.M
 800729f:	0000438f ffffffff 00000000 ffffffff     .C..............
 80072af:	00000000 ffffffff ffffffff ffffffff     ................
 80072bf:	ffffffff 79706f43 68676972 30322074     ....Copyright 20
 80072cf:	202d3831 43207962 6b6e696f 20657469     18- by Coinkite 
 80072df:	2e636e49 206b7700 6e006c66 6573206f     Inc..wk fl.no se
 80072ef:	00000072                                         r.

080072f1 <config_2.8469>:
 80072f1:	00000000 003c0000 01bc005c 01fc01fc     ......<.\.......
 8007301:	019c019c 01fc01fc 04dc03dc 08dc07dc     ................
 8007311:	01dc01fc 0100003c 12000000 00000000     ....<...........
 8007321:	01000000 08000000 00000000                       ...........

0800732c <CSWTCH.38>:
 800732c:	001e0000 0078001e 02580078 02580258     ......x.x.X.X.X.
 800733c:	02580258 0e100e10 0e100e10 0e100e10     X.X.............
 800734c:	0e100e10 0e100e10 38403840 38403840     ........@8@8@8@8
 800735c:	38403840 38403840 38403840 38403840     @8@8@8@8@8@8@8@8
 800736c:	38403840 38403840 38403840 38403840     @8@8@8@8@8@8@8@8
 800737c:	38403840 38403840 38403840 38403840     @8@8@8@8@8@8@8@8
 800738c:	38403840                                @8@8

08007390 <version_string>:
 8007390:	2e302e31 69742030 323d656d 30383130     1.0.0 time=20180
 80073a0:	2e343237 38323531 67203232 6d3d7469     724.152822 git=m
 80073b0:	65747361 63364072 39343565 00000032     aster@6ce5492...
 80073c0:	00000200 00000001 00000000 00000001     ................
 80073d0:	00000000                                ....

080073d4 <k>:
 80073d4:	428a2f98 71374491 b5c0fbcf e9b5dba5     ./.B.D7q........
 80073e4:	3956c25b 59f111f1 923f82a4 ab1c5ed5     [.V9...Y..?..^..
 80073f4:	d807aa98 12835b01 243185be 550c7dc3     .....[....1$.}.U
 8007404:	72be5d74 80deb1fe 9bdc06a7 c19bf174     t].r........t...
 8007414:	e49b69c1 efbe4786 0fc19dc6 240ca1cc     .i...G.........$
 8007424:	2de92c6f 4a7484aa 5cb0a9dc 76f988da     o,.-..tJ...\...v
 8007434:	983e5152 a831c66d b00327c8 bf597fc7     RQ>.m.1..'....Y.
 8007444:	c6e00bf3 d5a79147 06ca6351 14292967     ....G...Qc..g)).
 8007454:	27b70a85 2e1b2138 4d2c6dfc 53380d13     ...'8!...m,M..8S
 8007464:	650a7354 766a0abb 81c2c92e 92722c85     Ts.e..jv.....,r.
 8007474:	a2bfe8a1 a81a664b c24b8b70 c76c51a3     ....Kf..p.K..Ql.
 8007484:	d192e819 d6990624 f40e3585 106aa070     ....$....5..p.j.
 8007494:	19a4c116 1e376c08 2748774c 34b0bcb5     .....l7.LwH'...4
 80074a4:	391c0cb3 4ed8aa4a 5b9cca4f 682e6ff3     ...9J..NO..[.o.h
 80074b4:	748f82ee 78a5636f 84c87814 8cc70208     ...toc.x.x......
 80074c4:	90befffa a4506ceb bef9a3f7 c67178f2     .....lP......xq.

080074d4 <curve_secp256k1>:
 80074d4:	01002008 fffffc2f fffffffe ffffffff     . ../...........
 80074e4:	ffffffff ffffffff ffffffff ffffffff     ................
 80074f4:	ffffffff d0364141 bfd25e8c af48a03b     ....AA6..^..;.H.
 8007504:	baaedce6 fffffffe ffffffff ffffffff     ................
 8007514:	ffffffff 16f81798 59f2815b 2dce28d9     ........[..Y.(.-
 8007524:	029bfcdb ce870b07 55a06295 f9dcbbac     .........b.U....
 8007534:	79be667e fb10d4b8 9c47d08f a6855419     ~f.y......G..T..
 8007544:	fd17b448 0e1108a8 5da4fbfc 26a3c465     H..........]e..&
 8007554:	483ada77 00000007 00000000 00000000     w.:H............
	...
 8007578:	08006035 080058ef 08005a73 08005aa1     5`...X..sZ...Z..

Disassembly of section .relocate:

10006000 <flash_burn>:
//
    __attribute__((section(".ramfunc")))
    __attribute__((noinline))
    int
flash_burn(uint32_t address, uint64_t val)
{
10006000:	b530      	push	{r4, r5, lr}
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
10006002:	4d3f      	ldr	r5, [pc, #252]	; (10006100 <BL_SRAM_BASE+0x100>)
10006004:	692c      	ldr	r4, [r5, #16]
10006006:	493e      	ldr	r1, [pc, #248]	; (10006100 <BL_SRAM_BASE+0x100>)
10006008:	03e4      	lsls	r4, r4, #15
1000600a:	d4fb      	bmi.n	10006004 <flash_burn+0x4>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
1000600c:	690c      	ldr	r4, [r1, #16]
1000600e:	07a5      	lsls	r5, r4, #30
10006010:	d41e      	bmi.n	10006050 <flash_burn+0x50>
10006012:	690c      	ldr	r4, [r1, #16]
10006014:	0724      	lsls	r4, r4, #28
10006016:	d41b      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006018:	690c      	ldr	r4, [r1, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
1000601a:	06e5      	lsls	r5, r4, #27
1000601c:	d418      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
1000601e:	690c      	ldr	r4, [r1, #16]
10006020:	06a4      	lsls	r4, r4, #26
10006022:	d415      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
10006024:	690c      	ldr	r4, [r1, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006026:	0665      	lsls	r5, r4, #25
10006028:	d412      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
1000602a:	690c      	ldr	r4, [r1, #16]
1000602c:	0624      	lsls	r4, r4, #24
1000602e:	d40f      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
10006030:	690c      	ldr	r4, [r1, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
10006032:	05e5      	lsls	r5, r4, #23
10006034:	d40c      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
10006036:	690c      	ldr	r4, [r1, #16]
10006038:	05a4      	lsls	r4, r4, #22
1000603a:	d409      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
1000603c:	6909      	ldr	r1, [r1, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
1000603e:	0449      	lsls	r1, r1, #17
10006040:	d406      	bmi.n	10006050 <flash_burn+0x50>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
10006042:	492f      	ldr	r1, [pc, #188]	; (10006100 <BL_SRAM_BASE+0x100>)
10006044:	690c      	ldr	r4, [r1, #16]
10006046:	0425      	lsls	r5, r4, #16
10006048:	d402      	bmi.n	10006050 <flash_burn+0x50>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
1000604a:	698c      	ldr	r4, [r1, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
1000604c:	2c00      	cmp	r4, #0
1000604e:	da02      	bge.n	10006056 <flash_burn+0x56>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
10006050:	492b      	ldr	r1, [pc, #172]	; (10006100 <BL_SRAM_BASE+0x100>)
10006052:	6909      	ldr	r1, [r1, #16]
10006054:	e004      	b.n	10006060 <flash_burn+0x60>
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
10006056:	690c      	ldr	r4, [r1, #16]
10006058:	07e4      	lsls	r4, r4, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
1000605a:	bf44      	itt	mi
1000605c:	2401      	movmi	r4, #1
1000605e:	610c      	strmi	r4, [r1, #16]

    // just in case?
    _flash_wait_done();

    // clear any and all errors
    FLASH->SR = FLASH->SR & 0xffff;
10006060:	4927      	ldr	r1, [pc, #156]	; (10006100 <BL_SRAM_BASE+0x100>)
10006062:	690c      	ldr	r4, [r1, #16]
10006064:	b2a4      	uxth	r4, r4
10006066:	610c      	str	r4, [r1, #16]

    // disable data cache
    __HAL_FLASH_DATA_CACHE_DISABLE();
10006068:	680c      	ldr	r4, [r1, #0]
1000606a:	f424 6480 	bic.w	r4, r4, #1024	; 0x400
1000606e:	600c      	str	r4, [r1, #0]

    // Program double-word (64-bit) at a specified address
    // see FLASH_Program_DoubleWord(Address, Data);

    // Set PG bit
    SET_BIT(FLASH->CR, FLASH_CR_PG);
10006070:	694c      	ldr	r4, [r1, #20]
10006072:	f044 0401 	orr.w	r4, r4, #1
10006076:	614c      	str	r4, [r1, #20]

    // Program a double word
    *(__IO uint32_t *)(address) = (uint32_t)val;
10006078:	6002      	str	r2, [r0, #0]
    *(__IO uint32_t *)(address+4) = (uint32_t)(val >> 32);
1000607a:	6043      	str	r3, [r0, #4]
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
1000607c:	690a      	ldr	r2, [r1, #16]
1000607e:	4b20      	ldr	r3, [pc, #128]	; (10006100 <BL_SRAM_BASE+0x100>)
10006080:	03d0      	lsls	r0, r2, #15
10006082:	d4fb      	bmi.n	1000607c <flash_burn+0x7c>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
10006084:	691a      	ldr	r2, [r3, #16]
10006086:	0792      	lsls	r2, r2, #30
10006088:	d41e      	bmi.n	100060c8 <flash_burn+0xc8>
1000608a:	691a      	ldr	r2, [r3, #16]
1000608c:	0715      	lsls	r5, r2, #28
1000608e:	d41b      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006090:	691a      	ldr	r2, [r3, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
10006092:	06d4      	lsls	r4, r2, #27
10006094:	d418      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006096:	691a      	ldr	r2, [r3, #16]
10006098:	0690      	lsls	r0, r2, #26
1000609a:	d415      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
1000609c:	691a      	ldr	r2, [r3, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
1000609e:	0651      	lsls	r1, r2, #25
100060a0:	d412      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
100060a2:	691a      	ldr	r2, [r3, #16]
100060a4:	0612      	lsls	r2, r2, #24
100060a6:	d40f      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100060a8:	691a      	ldr	r2, [r3, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
100060aa:	05d5      	lsls	r5, r2, #23
100060ac:	d40c      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100060ae:	691a      	ldr	r2, [r3, #16]
100060b0:	0594      	lsls	r4, r2, #22
100060b2:	d409      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
100060b4:	691b      	ldr	r3, [r3, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100060b6:	0458      	lsls	r0, r3, #17
100060b8:	d406      	bmi.n	100060c8 <flash_burn+0xc8>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
100060ba:	4b11      	ldr	r3, [pc, #68]	; (10006100 <BL_SRAM_BASE+0x100>)
100060bc:	691a      	ldr	r2, [r3, #16]
100060be:	0411      	lsls	r1, r2, #16
100060c0:	d402      	bmi.n	100060c8 <flash_burn+0xc8>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
100060c2:	699a      	ldr	r2, [r3, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
100060c4:	2a00      	cmp	r2, #0
100060c6:	da03      	bge.n	100060d0 <flash_burn+0xd0>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
100060c8:	4b0d      	ldr	r3, [pc, #52]	; (10006100 <BL_SRAM_BASE+0x100>)
100060ca:	6918      	ldr	r0, [r3, #16]
    // Program a double word
    *(__IO uint32_t *)(address) = (uint32_t)val;
    *(__IO uint32_t *)(address+4) = (uint32_t)(val >> 32);

    rv = _flash_wait_done();
    if(rv) return rv;
100060cc:	b128      	cbz	r0, 100060da <flash_burn+0xda>
100060ce:	bd30      	pop	{r4, r5, pc}
        // Save an error code; somewhat random
        return FLASH->SR;
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
100060d0:	691a      	ldr	r2, [r3, #16]
100060d2:	07d2      	lsls	r2, r2, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
100060d4:	bf44      	itt	mi
100060d6:	2201      	movmi	r2, #1
100060d8:	611a      	strmi	r2, [r3, #16]

    rv = _flash_wait_done();
    if(rv) return rv;

    // If the program operation is completed, disable the PG or FSTPG Bit
    CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
100060da:	4b09      	ldr	r3, [pc, #36]	; (10006100 <BL_SRAM_BASE+0x100>)
100060dc:	695a      	ldr	r2, [r3, #20]
100060de:	f022 0201 	bic.w	r2, r2, #1
100060e2:	615a      	str	r2, [r3, #20]

    // Flush the caches to be sure of data consistency, and reenable.
    __HAL_FLASH_DATA_CACHE_RESET();
100060e4:	681a      	ldr	r2, [r3, #0]
100060e6:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
100060ea:	601a      	str	r2, [r3, #0]
100060ec:	681a      	ldr	r2, [r3, #0]
100060ee:	f422 5280 	bic.w	r2, r2, #4096	; 0x1000
100060f2:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_DATA_CACHE_ENABLE();
100060f4:	681a      	ldr	r2, [r3, #0]
100060f6:	f442 6280 	orr.w	r2, r2, #1024	; 0x400
100060fa:	601a      	str	r2, [r3, #0]

    return 0;
100060fc:	2000      	movs	r0, #0
}
100060fe:	bd30      	pop	{r4, r5, pc}
10006100:	40022000 	.word	0x40022000

10006104 <flash_page_erase>:
//
    __attribute__((section(".ramfunc")))
    __attribute__((noinline))
    int
flash_page_erase(uint32_t address)
{
10006104:	0ac0      	lsrs	r0, r0, #11
10006106:	b510      	push	{r4, lr}
    uint32_t    page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE;      // 2k pages
10006108:	b284      	uxth	r4, r0

    // protect ourselves!
    if(page_num < ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)) {
1000610a:	2c0f      	cmp	r4, #15
1000610c:	f240 8099 	bls.w	10006242 <flash_page_erase+0x13e>
        return 1;
    }

    // always operate on both banks.
    bool bank2 = (page_num >= 256);
    page_num &= 0xff;
10006110:	b2c2      	uxtb	r2, r0
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
10006112:	484d      	ldr	r0, [pc, #308]	; (10006248 <flash_page_erase+0x144>)
10006114:	6901      	ldr	r1, [r0, #16]
10006116:	4b4c      	ldr	r3, [pc, #304]	; (10006248 <flash_page_erase+0x144>)
10006118:	03c9      	lsls	r1, r1, #15
1000611a:	d4fb      	bmi.n	10006114 <flash_page_erase+0x10>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
1000611c:	6919      	ldr	r1, [r3, #16]
1000611e:	0788      	lsls	r0, r1, #30
10006120:	d41e      	bmi.n	10006160 <flash_page_erase+0x5c>
10006122:	6919      	ldr	r1, [r3, #16]
10006124:	0709      	lsls	r1, r1, #28
10006126:	d41b      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006128:	6919      	ldr	r1, [r3, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
1000612a:	06c8      	lsls	r0, r1, #27
1000612c:	d418      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
1000612e:	6919      	ldr	r1, [r3, #16]
10006130:	0689      	lsls	r1, r1, #26
10006132:	d415      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
10006134:	6919      	ldr	r1, [r3, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
10006136:	0648      	lsls	r0, r1, #25
10006138:	d412      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
1000613a:	6919      	ldr	r1, [r3, #16]
1000613c:	0609      	lsls	r1, r1, #24
1000613e:	d40f      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
10006140:	6919      	ldr	r1, [r3, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
10006142:	05c8      	lsls	r0, r1, #23
10006144:	d40c      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
10006146:	6919      	ldr	r1, [r3, #16]
10006148:	0589      	lsls	r1, r1, #22
1000614a:	d409      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
1000614c:	691b      	ldr	r3, [r3, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
1000614e:	045b      	lsls	r3, r3, #17
10006150:	d406      	bmi.n	10006160 <flash_page_erase+0x5c>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
10006152:	4b3d      	ldr	r3, [pc, #244]	; (10006248 <flash_page_erase+0x144>)
10006154:	6919      	ldr	r1, [r3, #16]
10006156:	0408      	lsls	r0, r1, #16
10006158:	d402      	bmi.n	10006160 <flash_page_erase+0x5c>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
1000615a:	6999      	ldr	r1, [r3, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
1000615c:	2900      	cmp	r1, #0
1000615e:	da02      	bge.n	10006166 <flash_page_erase+0x62>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
10006160:	4b39      	ldr	r3, [pc, #228]	; (10006248 <flash_page_erase+0x144>)
10006162:	691b      	ldr	r3, [r3, #16]
10006164:	e004      	b.n	10006170 <flash_page_erase+0x6c>
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
10006166:	6919      	ldr	r1, [r3, #16]
10006168:	07c9      	lsls	r1, r1, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
1000616a:	bf44      	itt	mi
1000616c:	2101      	movmi	r1, #1
1000616e:	6119      	strmi	r1, [r3, #16]

    // just in case?
    _flash_wait_done();

    // clear any and all errors
    FLASH->SR = FLASH->SR & 0xffff;
10006170:	4b35      	ldr	r3, [pc, #212]	; (10006248 <flash_page_erase+0x144>)
10006172:	6919      	ldr	r1, [r3, #16]
10006174:	b289      	uxth	r1, r1
10006176:	6119      	str	r1, [r3, #16]

    // disable data cache
    __HAL_FLASH_DATA_CACHE_DISABLE();
10006178:	6819      	ldr	r1, [r3, #0]
1000617a:	f421 6180 	bic.w	r1, r1, #1024	; 0x400
1000617e:	6019      	str	r1, [r3, #0]

    // choose appropriate bank to work on.
    if(bank2) {
        SET_BIT(FLASH->CR, FLASH_CR_BKER);
10006180:	6959      	ldr	r1, [r3, #20]

    // disable data cache
    __HAL_FLASH_DATA_CACHE_DISABLE();

    // choose appropriate bank to work on.
    if(bank2) {
10006182:	2cff      	cmp	r4, #255	; 0xff
        SET_BIT(FLASH->CR, FLASH_CR_BKER);
10006184:	bf8c      	ite	hi
10006186:	f441 6100 	orrhi.w	r1, r1, #2048	; 0x800
    } else {
        CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
1000618a:	f421 6100 	bicls.w	r1, r1, #2048	; 0x800
1000618e:	6159      	str	r1, [r3, #20]
    }

    // Proceed to erase the page
    MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (page_num << POSITION_VAL(FLASH_CR_PNB)));
10006190:	6959      	ldr	r1, [r3, #20]
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
{
  uint32_t result;

#if       (__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)
   __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
10006192:	f44f 60ff 	mov.w	r0, #2040	; 0x7f8
10006196:	fa90 f0a0 	rbit	r0, r0
1000619a:	fab0 f080 	clz	r0, r0
1000619e:	f421 61ff 	bic.w	r1, r1, #2040	; 0x7f8
100061a2:	fa02 f000 	lsl.w	r0, r2, r0
100061a6:	4308      	orrs	r0, r1
100061a8:	6158      	str	r0, [r3, #20]
    SET_BIT(FLASH->CR, FLASH_CR_PER);
100061aa:	695a      	ldr	r2, [r3, #20]
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
100061ac:	4926      	ldr	r1, [pc, #152]	; (10006248 <flash_page_erase+0x144>)
        CLEAR_BIT(FLASH->CR, FLASH_CR_BKER);
    }

    // Proceed to erase the page
    MODIFY_REG(FLASH->CR, FLASH_CR_PNB, (page_num << POSITION_VAL(FLASH_CR_PNB)));
    SET_BIT(FLASH->CR, FLASH_CR_PER);
100061ae:	f042 0202 	orr.w	r2, r2, #2
100061b2:	615a      	str	r2, [r3, #20]
    SET_BIT(FLASH->CR, FLASH_CR_STRT);
100061b4:	695a      	ldr	r2, [r3, #20]
100061b6:	f442 3280 	orr.w	r2, r2, #65536	; 0x10000
100061ba:	615a      	str	r2, [r3, #20]
    __attribute__((section(".ramfunc")))
    __attribute__((always_inline))
    static inline uint32_t
_flash_wait_done(void)
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
100061bc:	690a      	ldr	r2, [r1, #16]
100061be:	4b22      	ldr	r3, [pc, #136]	; (10006248 <flash_page_erase+0x144>)
100061c0:	03d4      	lsls	r4, r2, #15
100061c2:	d4fb      	bmi.n	100061bc <flash_page_erase+0xb8>
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
100061c4:	691a      	ldr	r2, [r3, #16]
100061c6:	0790      	lsls	r0, r2, #30
100061c8:	d41e      	bmi.n	10006208 <flash_page_erase+0x104>
100061ca:	691a      	ldr	r2, [r3, #16]
100061cc:	0711      	lsls	r1, r2, #28
100061ce:	d41b      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
100061d0:	691a      	ldr	r2, [r3, #16]
{
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
100061d2:	06d2      	lsls	r2, r2, #27
100061d4:	d418      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
100061d6:	691a      	ldr	r2, [r3, #16]
100061d8:	0694      	lsls	r4, r2, #26
100061da:	d415      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
100061dc:	691a      	ldr	r2, [r3, #16]
    while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY)) {
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
100061de:	0650      	lsls	r0, r2, #25
100061e0:	d412      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
100061e2:	691a      	ldr	r2, [r3, #16]
100061e4:	0611      	lsls	r1, r2, #24
100061e6:	d40f      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100061e8:	691a      	ldr	r2, [r3, #16]
        // busy wait
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
100061ea:	05d2      	lsls	r2, r2, #23
100061ec:	d40c      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100061ee:	691a      	ldr	r2, [r3, #16]
100061f0:	0594      	lsls	r4, r2, #22
100061f2:	d409      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
100061f4:	691b      	ldr	r3, [r3, #16]
    }

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
100061f6:	0458      	lsls	r0, r3, #17
100061f8:	d406      	bmi.n	10006208 <flash_page_erase+0x104>
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
100061fa:	4b13      	ldr	r3, [pc, #76]	; (10006248 <flash_page_erase+0x144>)
100061fc:	691a      	ldr	r2, [r3, #16]
100061fe:	0411      	lsls	r1, r2, #16
10006200:	d402      	bmi.n	10006208 <flash_page_erase+0x104>
#if defined (STM32L431xx) || defined (STM32L432xx) || defined (STM32L433xx) || defined (STM32L442xx) || defined (STM32L443xx) || \
    defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx) || defined (STM32L496xx) || defined (STM32L4A6xx)
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))   || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PEMPTY))
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
10006202:	699a      	ldr	r2, [r3, #24]

    if((__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PROGERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGAERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_SIZERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGSERR))  ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_MISERR)) || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_FASTERR)) ||
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_RDERR))  || (__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR)) ||
10006204:	2a00      	cmp	r2, #0
10006206:	da02      	bge.n	1000620e <flash_page_erase+0x10a>
#else
       (__HAL_FLASH_GET_FLAG(FLASH_FLAG_ECCD))
#endif
    ) {
        // Save an error code; somewhat random
        return FLASH->SR;
10006208:	4b0f      	ldr	r3, [pc, #60]	; (10006248 <flash_page_erase+0x144>)
1000620a:	691b      	ldr	r3, [r3, #16]
1000620c:	e004      	b.n	10006218 <flash_page_erase+0x114>
    }

    // Check FLASH End of Operation flag
    if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP)) {
1000620e:	691a      	ldr	r2, [r3, #16]
10006210:	07d2      	lsls	r2, r2, #31
        // Clear FLASH End of Operation pending bit
        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
10006212:	bf44      	itt	mi
10006214:	2201      	movmi	r2, #1
10006216:	611a      	strmi	r2, [r3, #16]

    // Wait til done
    _flash_wait_done();

    // If the erase operation is completed, disable the PER Bit
    CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
10006218:	4b0b      	ldr	r3, [pc, #44]	; (10006248 <flash_page_erase+0x144>)
1000621a:	695a      	ldr	r2, [r3, #20]
1000621c:	f422 62ff 	bic.w	r2, r2, #2040	; 0x7f8
10006220:	f022 0202 	bic.w	r2, r2, #2
10006224:	615a      	str	r2, [r3, #20]

    // Flush the caches to be sure of data consistency, and reenable.
    __HAL_FLASH_DATA_CACHE_RESET();
10006226:	681a      	ldr	r2, [r3, #0]
10006228:	f442 5280 	orr.w	r2, r2, #4096	; 0x1000
1000622c:	601a      	str	r2, [r3, #0]
1000622e:	681a      	ldr	r2, [r3, #0]
10006230:	f422 5280 	bic.w	r2, r2, #4096	; 0x1000
10006234:	601a      	str	r2, [r3, #0]
    __HAL_FLASH_DATA_CACHE_ENABLE();
10006236:	681a      	ldr	r2, [r3, #0]
10006238:	f442 6280 	orr.w	r2, r2, #1024	; 0x400
1000623c:	601a      	str	r2, [r3, #0]

    return 0;
1000623e:	2000      	movs	r0, #0
10006240:	bd10      	pop	{r4, pc}
{
    uint32_t    page_num = (address & 0x7ffffff) / FLASH_PAGE_SIZE;      // 2k pages

    // protect ourselves!
    if(page_num < ((BL_FLASH_SIZE + BL_NVROM_SIZE) / FLASH_PAGE_SIZE)) {
        return 1;
10006242:	2001      	movs	r0, #1
    // Flush the caches to be sure of data consistency, and reenable.
    __HAL_FLASH_DATA_CACHE_RESET();
    __HAL_FLASH_DATA_CACHE_ENABLE();

    return 0;
}
10006244:	bd10      	pop	{r4, pc}
10006246:	bf00      	nop
10006248:	40022000 	.word	0x40022000
