/home/nickb/.local/qmk.pFE/qmk_base/.build/kinesis_kint41_default.elf: file format elf32-littlearm Disassembly of section .vectors: <__vectors_base__>: .word 0x20000400 .word 0x600018e9 .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600053db .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600067a5 .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x60006951 .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb .word 0x600018eb ... : .. .b.` Disassembly of section .text: <_crt0_entry>: cpsid i ldr r0, [pc, #152] @ () msr MSP, r0 ldr r0, [pc, #148] @ () msr PSP, r0 ldr r0, [pc, #148] @ () ldr r1, [pc, #148] @ () str r0, [r1, #0] movs r0, #2 msr CONTROL, r0 isb sy bl <__cpu_init> bl <__early_init> mov.w r0, #1431655765 @ 0x55555555 ldr r1, [pc, #128] @ () ldr r2, [pc, #108] @ () : cmp r1, r2 itt cc strcc.w r0, [r1], #4 bcc.n ldr r1, [pc, #116] @ () ldr r2, [pc, #100] @ () : cmp r1, r2 itt cc strcc.w r0, [r1], #4 bcc.n ldr r1, [pc, #108] @ () ldr r2, [pc, #108] @ () ldr r3, [pc, #112] @ () : cmp r2, r3 ittt cc ldrcc.w r0, [r1], #4 strcc.w r0, [r2], #4 bcc.n movs r0, #0 ldr r1, [pc, #96] @ () ldr r2, [pc, #100] @ () : cmp r1, r2 itt cc strcc.w r0, [r1], #4 bcc.n bl <__init_ram_areas> bl <__late_init> ldr r4, [pc, #84] @ () ldr r5, [pc, #84] @ () : cmp r4, r5 bge.n ldr.w r1, [r4], #4 blx r1 b.n : bl
ldr r4, [pc, #72] @ () ldr r5, [pc, #72] @ () : cmp r4, r5 bge.n ldr.w r1, [r4], #4 blx r1 b.n : b.w <__default_exit> .short 0x0000 .word 0x20000400 .word 0x20000c00 .word 0x60001400 .word 0xe000ed08 .word 0x20000000 .word 0x20000400 .word 0x60009028 .word 0x20000c00 .word 0x20000d34 .word 0x20001000 .word 0x200021a4 .word 0x60001808 .word 0x60001808 .word 0x60001808 .word 0x60001808 : b.n <_crt0_entry> : bl <_unhandled_exception> <_unhandled_exception>: b.n <_unhandled_exception> <__port_switch>: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} str.w sp, [r1, #12] ldr.w sp, [r0, #12] ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} <__port_thread_start>: movs r3, #0 msr BASEPRI, r3 mov r0, r5 blx r4 movs r0, #0 bl <.zombies>: b.n <.zombies> <__port_switch_from_isr>: bl <__port_exit_from_isr>: svc 0 b.n <__port_exit_from_isr+0x2> ... <__aeabi_uldivmod>: cbnz r3, <__aeabi_uldivmod+0x18> cbnz r2, <__aeabi_uldivmod+0x18> cmp r1, #0 it eq cmpeq r0, #0 itt ne movne.w r1, #4294967295 @ 0xffffffff movne.w r0, #4294967295 @ 0xffffffff b.w <__aeabi_idiv0> sub.w ip, sp, #8 strd ip, lr, [sp, #-16]! bl <__udivmoddi4> ldr.w lr, [sp, #4] ldrd r2, r3, [sp, #8] add sp, #16 bx lr <__udivmoddi4>: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} mov lr, r0 mov ip, r1 mov r0, r1 ldr r6, [sp, #32] mov r5, r2 mov r4, lr mov r1, r3 cmp r3, #0 bne.w <__udivmoddi4+0x19c> cmp r5, r0 clz r2, r2 bls.n <__udivmoddi4+0xac> cbz r2, <__udivmoddi4+0x36> rsb r3, r2, #32 lsl.w ip, r0, r2 lsr.w r3, lr, r3 lsls r5, r2 orr.w ip, r3, ip lsls r4, r2 mov.w lr, r5, lsr #16 uxth r0, r5 udiv r8, ip, lr lsrs r3, r4, #16 mls ip, lr, r8, ip mul.w r9, r8, r0 orr.w r3, r3, ip, lsl #16 cmp r9, r3 bls.n <__udivmoddi4+0xa4> adds r3, r5, r3 add.w r7, r8, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x64> cmp r9, r3 bls.n <__udivmoddi4+0x64> sub.w r7, r8, #2 add r3, r5 sub.w r3, r3, r9 uxth r4, r4 udiv ip, r3, lr mls r3, lr, ip, r3 mul.w r0, ip, r0 orr.w r4, r4, r3, lsl #16 cmp r0, r4 bls.n <__udivmoddi4+0xa8> adds r4, r5, r4 add.w r3, ip, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x90> cmp r0, r4 bls.n <__udivmoddi4+0x90> sub.w r3, ip, #2 add r4, r5 subs r4, r4, r0 orr.w r0, r3, r7, lsl #16 cbz r6, <__udivmoddi4+0xa0> lsrs r4, r2 movs r3, #0 str r4, [r6, #0] str r3, [r6, #4] ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} mov r7, r8 b.n <__udivmoddi4+0x64> mov r3, ip b.n <__udivmoddi4+0x90> cbnz r2, <__udivmoddi4+0x114> subs r3, r0, r5 movs r1, #1 mov.w lr, r5, lsr #16 uxth r7, r5 udiv ip, r3, lr lsrs r0, r4, #16 mls r3, lr, ip, r3 mul.w r8, ip, r7 orr.w r3, r0, r3, lsl #16 cmp r8, r3 bls.n <__udivmoddi4+0x194> adds r3, r5, r3 add.w r0, ip, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0xe0> cmp r8, r3 bls.n <__udivmoddi4+0xe0> sub.w r0, ip, #2 add r3, r5 sub.w r3, r3, r8 uxth r4, r4 udiv ip, r3, lr mls r3, lr, ip, r3 mul.w r7, ip, r7 orr.w r4, r4, r3, lsl #16 cmp r7, r4 bls.n <__udivmoddi4+0x198> adds r4, r5, r4 add.w r3, ip, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x10c> cmp r7, r4 bls.n <__udivmoddi4+0x10c> sub.w r3, ip, #2 add r4, r5 subs r4, r4, r7 orr.w r0, r3, r0, lsl #16 b.n <__udivmoddi4+0x96> rsb r3, r2, #32 lsr.w r1, r0, r3 lsls r5, r2 lsls r0, r2 lsr.w r3, lr, r3 orrs r3, r0 mov.w lr, r5, lsr #16 uxth r7, r5 udiv ip, r1, lr mls r0, lr, ip, r1 lsrs r1, r3, #16 mul.w r8, ip, r7 orr.w r1, r1, r0, lsl #16 cmp r8, r1 lsl.w r4, r4, r2 bls.n <__udivmoddi4+0x18c> adds r1, r5, r1 add.w r0, ip, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x158> cmp r8, r1 bls.n <__udivmoddi4+0x158> sub.w r0, ip, #2 add r1, r5 sub.w r1, r1, r8 uxth r3, r3 udiv ip, r1, lr mls r1, lr, ip, r1 mul.w r7, ip, r7 orr.w r3, r3, r1, lsl #16 cmp r7, r3 bls.n <__udivmoddi4+0x190> adds r3, r5, r3 add.w r1, ip, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x184> cmp r7, r3 bls.n <__udivmoddi4+0x184> sub.w r1, ip, #2 add r3, r5 subs r3, r3, r7 orr.w r1, r1, r0, lsl #16 b.n <__udivmoddi4+0xb2> mov r0, ip b.n <__udivmoddi4+0x158> mov r1, ip b.n <__udivmoddi4+0x184> mov r0, ip b.n <__udivmoddi4+0xe0> mov r3, ip b.n <__udivmoddi4+0x10c> cmp r3, r0 bls.n <__udivmoddi4+0x1ae> cbnz r6, <__udivmoddi4+0x1a8> movs r1, #0 mov r0, r1 b.n <__udivmoddi4+0xa0> strd lr, r0, [r6] b.n <__udivmoddi4+0x1a2> clz r7, r3 cbnz r7, <__udivmoddi4+0x1d8> cmp r3, r0 bcc.n <__udivmoddi4+0x1bc> cmp r2, lr bhi.n <__udivmoddi4+0x1ce> subs.w r4, lr, r2 sbc.w r3, r0, r3 movs r0, #1 mov ip, r3 cbnz r6, <__udivmoddi4+0x1d2> movs r1, #0 b.n <__udivmoddi4+0xa0> mov r0, r7 b.n <__udivmoddi4+0x1c8> strd r4, ip, [r6] b.n <__udivmoddi4+0x1ca> rsb ip, r7, #32 lsls r3, r7 lsr.w r4, r2, ip orrs r4, r3 lsr.w r1, lr, ip lsr.w r3, r0, ip lsls r0, r7 orrs r1, r0 mov.w r9, r4, lsr #16 lsl.w r5, lr, r7 udiv r8, r3, r9 uxth.w lr, r4 mls r0, r9, r8, r3 lsrs r3, r1, #16 mul.w sl, r8, lr orr.w r3, r3, r0, lsl #16 cmp sl, r3 lsl.w r2, r2, r7 bls.n <__udivmoddi4+0x298> adds r3, r4, r3 add.w r0, r8, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x228> cmp sl, r3 bls.n <__udivmoddi4+0x228> sub.w r0, r8, #2 add r3, r4 sub.w r3, r3, sl uxth r1, r1 udiv r8, r3, r9 mls r3, r9, r8, r3 mul.w lr, r8, lr orr.w r1, r1, r3, lsl #16 cmp lr, r1 bls.n <__udivmoddi4+0x29c> adds r1, r4, r1 add.w r3, r8, #4294967295 @ 0xffffffff bcs.n <__udivmoddi4+0x254> cmp lr, r1 bls.n <__udivmoddi4+0x254> sub.w r3, r8, #2 add r1, r4 orr.w r0, r3, r0, lsl #16 umull r9, r8, r0, r2 sub.w r1, r1, lr cmp r1, r8 mov lr, r9 mov r3, r8 bcc.n <__udivmoddi4+0x26e> bne.n <__udivmoddi4+0x278> cmp r5, r9 bcs.n <__udivmoddi4+0x278> subs.w lr, r9, r2 sbc.w r3, r8, r4 subs r0, #1 cmp r6, #0 beq.n <__udivmoddi4+0x1ca> subs.w r2, r5, lr sbc.w r1, r1, r3 lsl.w ip, r1, ip lsr.w r3, r2, r7 orr.w r3, ip, r3 lsrs r1, r7 strd r3, r1, [r6] b.n <__udivmoddi4+0x1ca> mov r0, r8 b.n <__udivmoddi4+0x228> mov r3, r8 b.n <__udivmoddi4+0x254> <__aeabi_idiv0>: bx lr nop : and.w r1, r1, #255 @ 0xff cmp r2, #16 blt.n tst.w r0, #7 beq.n ldrb.w r3, [r0], #1 subs r2, #1 cmp r3, r1 beq.n tst.w r0, #7 cbz r2, bne.n push {r4, r5, r6, r7} orr.w r1, r1, r1, lsl #8 orr.w r1, r1, r1, lsl #16 bic.w r4, r2, #7 mvns.w r7, #0 movs r3, #0 ldrd r5, r6, [r0], #8 subs r4, #8 eor.w r5, r5, r1 eor.w r6, r6, r1 uadd8 r5, r5, r7 sel r5, r3, r7 uadd8 r6, r6, r7 sel r6, r5, r7 cbnz r6, bne.n pop {r4, r5, r6, r7} and.w r1, r1, #255 @ 0xff and.w r2, r2, #7 cbz r2, ldrb.w r3, [r0], #1 subs r2, #1 eor.w r3, r3, r1 cbz r3, bne.n movs r0, #0 bx lr subs r0, #1 bx lr cmp r5, #0 itte eq moveq r5, r6 subeq r0, #3 subne r0, #7 tst.w r5, #1 bne.n adds r0, #1 tst.w r5, #256 @ 0x100 ittt eq addeq r0, #1 tsteq.w r5, #98304 @ 0x18000 addeq r0, #1 pop {r4, r5, r6, r7} subs r0, #1 bx lr nop : #include "quantum.h" #define LED_POWER LINE_PIN13 void matrix_init_kb(void) { push {r4, lr} matrix_init_user(); // Turn on the Teensy 4.x Power LED: setPinOutput(LED_POWER); ldr r4, [pc, #28] @ () matrix_init_user(); bl setPinOutput(LED_POWER); mov r0, r4 movs r2, #6 movs r1, #13 bl <_pal_lld_setpadmode> writePinHigh(LED_POWER); mov r0, r4 movs r2, #1 } ldmia.w sp!, {r4, lr} writePinHigh(LED_POWER); movs r1, #13 b.w <_pal_lld_writepad> .word 0x42004000 : // should not be modified, i.e. it is safe to call during keyboard matrix scan. // // ChibiOS enables the cycle counter in chcore_v7m.c: // https://github.com/ChibiOS/ChibiOS/blob/b63023915c304092acb9f33bbab40f3ec07a7f0e/os/common/ports/ARMCMx/chcore_v7m.c#L263 static void delay_inline(const uint32_t cycles) { const uint32_t start = DWT->CYCCNT; ldr r2, [pc, #16] @ () ldr r0, [r2, #4] while ((DWT->CYCCNT - start) < cycles) { movw r1, #11999 @ 0x2edf ldr r3, [r2, #4] subs r3, r3, r0 cmp r3, r1 bls.n // on a combination of KB600LF+stapelberg v2020-06-30+teensy41. // 600 cycles at 0.6 cycles/ns == 1μs const uint32_t cycles_per_us = 600; delay_inline(20 * cycles_per_us); } bx lr nop .word 0xe0001000 : #else _Static_assert(NUM_KEYMAP_LAYERS_RAW <= MAX_LAYER, "Number of keymap layers exceeds maximum set by LAYER_STATE_(8|16|32)BIT"); #endif uint16_t keycode_at_keymap_location_raw(uint8_t layer_num, uint8_t row, uint8_t column) { if (layer_num < NUM_KEYMAP_LAYERS_RAW && row < MATRIX_ROWS && column < MATRIX_COLS) { cbnz r0, cmp r1, #14 bhi.n cmp r2, #6 bhi.n return pgm_read_word(&keymaps[layer_num][row][column]); rsb r1, r1, r1, lsl #3 ldr r3, [pc, #12] @ () add r2, r1 ldrh.w r0, [r3, r2, lsl #1] bx lr } return KC_TRNS; movs r0, #1 } bx lr .word 0x60008a14 : __attribute__((weak)) uint16_t keycode_at_keymap_location(uint8_t layer_num, uint8_t row, uint8_t column) { return keycode_at_keymap_location_raw(layer_num, row, column); b.w : return pre_process_record_user(keycode, record); } __attribute__((weak)) bool pre_process_record_user(uint16_t keycode, keyrecord_t *record) { return true; } movs r0, #1 bx lr : __attribute__((weak)) bool pre_process_record_kb(uint16_t keycode, keyrecord_t *record) { push {r3, lr} return pre_process_record_user(keycode, record); bl } pop {r3, pc} : __attribute__((weak)) bool process_action_kb(keyrecord_t *record) { return true; } movs r0, #1 bx lr : __attribute__((weak)) bool process_record_kb(uint16_t keycode, keyrecord_t *record) { return process_record_user(keycode, record); } __attribute__((weak)) bool process_record_user(uint16_t keycode, keyrecord_t *record) { movs r0, #1 bx lr : __attribute__((weak)) bool process_record_kb(uint16_t keycode, keyrecord_t *record) { push {r3, lr} return process_record_user(keycode, record); bl } pop {r3, pc} : __attribute__((weak)) void post_process_record_kb(uint16_t keycode, keyrecord_t *record) { post_process_record_user(keycode, record); } __attribute__((weak)) void post_process_record_user(uint16_t keycode, keyrecord_t *record) {} bx lr : __attribute__((weak)) void post_process_record_kb(uint16_t keycode, keyrecord_t *record) { push {r3, lr} post_process_record_user(keycode, record); bl } pop {r3, pc} ... : * retains the correct keycode after a layer change, if the key is still pressed. * "update_layer_cache" is to ensure that it only updates the layer cache when * appropriate, otherwise, it will update it and cause layer tap (and other keys) * from triggering properly. */ uint16_t get_event_keycode(keyevent_t event, bool update_layer_cache) { push {r0, r1, r4, lr} add r3, sp, #8 stmdb r3, {r0, r1} #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) /* TODO: Use store_or_get_action() or a similar function. */ if (!disable_action_cache) { ldr r3, [pc, #60] @ () ldrb r3, [r3, #0] cbnz r3, uint8_t layer; if (event.pressed && update_layer_cache) { ldrb.w r3, [sp, #5] cbz r3, cbz r2, layer = layer_switch_get_layer(event.key); bl mov r4, r0 update_source_layers_cache(event.key, layer); mov r1, r0 ldr r0, [sp, #0] bl } else { layer = read_source_layers_cache(event.key); } return keymap_key_to_keycode(layer, event.key); ldr r1, [sp, #0] mov r0, r4 } else #endif return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); } add sp, #8 ldmia.w sp!, {r4, lr} return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); b.w layer = read_source_layers_cache(event.key); ldr r0, [sp, #0] bl mov r4, r0 b.n return keymap_key_to_keycode(layer_switch_get_layer(event.key), event.key); ldr r0, [sp, #0] bl ldr r1, [sp, #0] b.n nop .word 0x20001008 : uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { mov r3, r0 push {r4} return get_event_keycode(record->event, update_layer_cache); ldrh r0, [r0, #0] ldrh r4, [r3, #2] uint16_t get_record_keycode(keyrecord_t *record, bool update_layer_cache) { mov r2, r1 return get_event_keycode(record->event, update_layer_cache); orr.w r0, r0, r4, lsl #16 ldrh r1, [r3, #4] } pop {r4} return get_event_keycode(record->event, update_layer_cache); b.w : /* Get keycode, and then process pre tapping functionality */ bool pre_process_record_quantum(keyrecord_t *record) { push {r4, lr} uint16_t keycode = get_record_keycode(record, true); movs r1, #1 bool pre_process_record_quantum(keyrecord_t *record) { mov r4, r0 uint16_t keycode = get_record_keycode(record, true); bl return pre_process_record_kb(keycode, record) && mov r1, r4 bl #ifdef COMBO_ENABLE process_combo(keycode, record) && #endif true; } pop {r4, pc} : /* Get keycode, and then call keyboard function */ void post_process_record_quantum(keyrecord_t *record) { push {r4, lr} uint16_t keycode = get_record_keycode(record, false); movs r1, #0 void post_process_record_quantum(keyrecord_t *record) { mov r4, r0 uint16_t keycode = get_record_keycode(record, false); bl post_process_record_kb(keycode, record); mov r1, r4 bl } pop {r4, pc} : // Override these functions in your keymap file to play different tunes on // different events such as startup and bootloader jump __attribute__((weak)) bool shutdown_user(bool jump_to_bootloader) { return true; } movs r0, #1 bx lr : __attribute__((weak)) bool shutdown_kb(bool jump_to_bootloader) { push {r3, lr} if (!shutdown_user(jump_to_bootloader)) { bl return false; } return true; } pop {r3, pc} : void shutdown_quantum(bool jump_to_bootloader) { push {r4, lr} mov r4, r0 clear_keyboard(); bl shutdown_kb(jump_to_bootloader); mov r0, r4 bl } ldmia.w sp!, {r4, lr} wait_ms(250); movw r0, #2500 @ 0x9c4 b.w : void reset_keyboard(void) { push {r3, lr} shutdown_quantum(true); movs r0, #1 bl } ldmia.w sp!, {r3, lr} bootloader_jump(); b.w : void soft_reset_keyboard(void) { push {r3, lr} shutdown_quantum(false); movs r0, #0 bl } ldmia.w sp!, {r3, lr} mcu_reset(); b.w : bool process_record_quantum(keyrecord_t *record) { push {r3, r4, r5, lr} uint16_t keycode = get_record_keycode(record, true); movs r1, #1 bool process_record_quantum(keyrecord_t *record) { mov r5, r0 uint16_t keycode = get_record_keycode(record, true); bl process_record_kb(keycode, record) && mov r1, r5 uint16_t keycode = get_record_keycode(record, true); mov r4, r0 process_record_kb(keycode, record) && bl process_magic(keycode, record) && cbz r0, process_space_cadet(keycode, record) && mov r1, r5 mov r0, r4 bl process_record_kb(keycode, record) && cbz r0, process_magic(keycode, record) && mov r1, r5 mov r0, r4 bl process_space_cadet(keycode, record) && cbz r0, process_grave_esc(keycode, record) && mov r1, r5 mov r0, r4 bl process_magic(keycode, record) && cbz r0, if (record->event.pressed) { ldrb r3, [r5, #5] cbz r3, switch (keycode) { movw r3, #31834 @ 0x7c5a cmp r4, r3 beq.n bhi.n movw r3, #31745 @ 0x7c01 cmp r4, r3 beq.n movw r3, #31747 @ 0x7c03 cmp r4, r3 beq.n cmp.w r4, #31744 @ 0x7c00 beq.n return process_action_kb(record); mov r0, r5 bl b.n switch (keycode) { movw r3, #31835 @ 0x7c5b cmp r4, r3 beq.n movw r3, #31836 @ 0x7c5c cmp r4, r3 bne.n oneshot_toggle(); bl break; b.n reset_keyboard(); bl return false; movs r0, #0 } pop {r3, r4, r5, pc} eeconfig_disable(); bl soft_reset_keyboard(); bl return false; b.n oneshot_enable(); bl break; b.n oneshot_disable(); bl break; b.n : void suspend_power_down_quantum(void) { push {r3, lr} suspend_power_down_kb(); bl # if defined(POINTING_DEVICE_ENABLE) // run to ensure scanning occurs while suspended pointing_device_task(); # endif #endif } ldmia.w sp!, {r3, lr} led_suspend(); b.w : __attribute__((weak)) void suspend_wakeup_init_quantum(void) { push {r3, lr} #ifdef BACKLIGHT_ENABLE backlight_init(); #endif // Restore LED indicators led_wakeup(); bl #endif #if defined(RGB_MATRIX_ENABLE) rgb_matrix_set_suspend_state(false); #endif suspend_wakeup_init_kb(); } ldmia.w sp!, {r3, lr} suspend_wakeup_init_kb(); b.w : /** \brief Lock LED set callback - keymap/user level * * \deprecated Use led_update_user() instead. */ __attribute__((weak)) void led_set_user(uint8_t usb_led) {} bx lr : * * \return True if led_update_kb() should run its own code, false otherwise. */ __attribute__((weak)) bool led_update_user(led_t led_state) { return true; } movs r0, #1 bx lr : /** \brief Write LED state to hardware */ __attribute__((weak)) void led_update_ports(led_t led_state) { #if LED_PIN_ON_STATE == 0 // invert the whole thing to avoid having to conditionally !led_state.x later led_state.raw = ~led_state.raw; mvns r2, r0 __attribute__((weak)) void led_update_ports(led_t led_state) { push {r4, lr} led_state.raw = ~led_state.raw; uxtb r4, r2 #endif #ifdef LED_NUM_LOCK_PIN writePin(LED_NUM_LOCK_PIN, led_state.num_lock); ands.w r2, r2, #1 it ne movne r2, #1 movs r1, #26 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_writepad> #endif #ifdef LED_CAPS_LOCK_PIN writePin(LED_CAPS_LOCK_PIN, led_state.caps_lock); ands.w r2, r4, #2 ldr r0, [pc, #48] @ () it ne movne r2, #1 movs r1, #12 bl <_pal_lld_writepad> #endif #ifdef LED_SCROLL_LOCK_PIN writePin(LED_SCROLL_LOCK_PIN, led_state.scroll_lock); ands.w r2, r4, #4 it ne movne r2, #1 movs r1, #25 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_writepad> #endif #ifdef LED_COMPOSE_PIN writePin(LED_COMPOSE_PIN, led_state.compose); ands.w r2, r4, #8 it ne movne r2, #1 #endif #ifdef LED_KANA_PIN writePin(LED_KANA_PIN, led_state.kana); #endif } ldmia.w sp!, {r4, lr} writePin(LED_COMPOSE_PIN, led_state.compose); movs r1, #24 mov.w r0, #1107296256 @ 0x42000000 b.w <_pal_lld_writepad> .word 0x42004000 : __attribute__((weak)) bool led_update_kb(led_t led_state) { push {r3, r4, r5, lr} mov r5, r0 bool res = led_update_user(led_state); bl if (res) { mov r4, r0 cbz r0, led_update_ports(led_state); mov r0, r5 bl } mov r0, r4 pop {r3, r4, r5, pc} ... : /** \brief Initialise any LED related hardware and/or state */ __attribute__((weak)) void led_init_ports(void) { push {r4, lr} #ifdef LED_NUM_LOCK_PIN setPinOutput(LED_NUM_LOCK_PIN); movs r2, #6 writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE); #endif #ifdef LED_CAPS_LOCK_PIN setPinOutput(LED_CAPS_LOCK_PIN); ldr r4, [pc, #92] @ () setPinOutput(LED_NUM_LOCK_PIN); movs r1, #26 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_setpadmode> writePin(LED_NUM_LOCK_PIN, !LED_PIN_ON_STATE); movs r2, #1 movs r1, #26 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_writepad> setPinOutput(LED_CAPS_LOCK_PIN); mov r0, r4 movs r2, #6 movs r1, #12 bl <_pal_lld_setpadmode> writePin(LED_CAPS_LOCK_PIN, !LED_PIN_ON_STATE); mov r0, r4 movs r2, #1 movs r1, #12 bl <_pal_lld_writepad> #endif #ifdef LED_SCROLL_LOCK_PIN setPinOutput(LED_SCROLL_LOCK_PIN); movs r2, #6 movs r1, #25 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_setpadmode> writePin(LED_SCROLL_LOCK_PIN, !LED_PIN_ON_STATE); movs r2, #1 movs r1, #25 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_writepad> #endif #ifdef LED_COMPOSE_PIN setPinOutput(LED_COMPOSE_PIN); movs r2, #6 movs r1, #24 mov.w r0, #1107296256 @ 0x42000000 bl <_pal_lld_setpadmode> #endif #ifdef LED_KANA_PIN setPinOutput(LED_KANA_PIN); writePin(LED_KANA_PIN, !LED_PIN_ON_STATE); #endif } ldmia.w sp!, {r4, lr} writePin(LED_COMPOSE_PIN, !LED_PIN_ON_STATE); movs r2, #1 movs r1, #24 mov.w r0, #1107296256 @ 0x42000000 b.w <_pal_lld_writepad> .word 0x42004000 : /** \brief Entrypoint for protocol to LED binding */ __attribute__((weak)) void led_set(uint8_t usb_led) { push {r4, lr} mov r4, r0 #ifdef BACKLIGHT_CAPS_LOCK handle_backlight_caps_lock((led_t)usb_led); #endif led_set_user(usb_led); bl led_update_kb((led_t)usb_led); mov r0, r4 bl } pop {r4, pc} : /** \brief Trigger behaviour on transition to suspend */ void led_suspend(void) { push {r3, lr} if (is_backlight_enabled()) { // Don't try to turn off Caps Lock indicator as it is backlight and backlight is already off leds_off.caps_lock = true; } #endif led_set(leds_off.raw); movs r0, #0 bl } pop {r3, pc} : /** \brief Trigger behaviour on transition from suspend */ void led_wakeup(void) { push {r3, lr} led_set(host_keyboard_leds()); bl bl } pop {r3, pc} ... : /** \brief set host led state * * Only sets state if change detected */ void led_task(void) { push {r4, lr} static uint8_t last_led_status = 0; // update LED uint8_t led_status = host_keyboard_leds(); bl if (last_led_status != led_status) { ldr r3, [pc, #28] @ () ldrb r2, [r3, #0] cmp r2, r0 uint8_t led_status = host_keyboard_leds(); mov r4, r0 if (last_led_status != led_status) { beq.n last_led_status = led_status; strb r0, [r3, #0] last_led_modification_time = timer_read32(); bl ldr r3, [pc, #16] @ () str r0, [r3, #0] if (debug_keyboard) { dprintf("led_task: %02X\n", led_status); } led_set(led_status); mov r0, r4 bl } } pop {r4, pc} nop .word 0x20001000 .word 0x20001004 : /** \brief Called to execute an action. * * FIXME: Needs documentation. */ void action_exec(keyevent_t event) { push {r0, r1, r2, r3, r4, lr} mov r4, sp stmia.w r4, {r0, r1} #if defined(RETRO_TAPPING) || defined(RETRO_TAPPING_PER_KEY) || (defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT)) retro_tapping_counter++; #endif } if (event.pressed) { ldrb.w r3, [sp, #5] cbz r3, // clear the potential weak mods left by previously pressed keys clear_weak_mods(); bl if (IS_EVENT(event)) { process_hand_swap(&event); } #endif keyrecord_t record = {.event = event}; movs r3, #0 strh.w r3, [sp, #14] ldmia.w r4, {r0, r1} strh.w r1, [sp, #12] # if defined(AUTO_SHIFT_ENABLE) && defined(RETRO_SHIFT) if (event.pressed) { retroshift_poll_time(&event); } # endif if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { uxtb r1, r1 keyrecord_t record = {.event = event}; str r0, [sp, #8] add r4, sp, #8 if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { cbnz r1, action_tapping_process(record); ldmia.w r4, {r0, r1} bl ac_dprintf("processed: "); debug_record(record); dprintln(); } #endif } add sp, #16 pop {r4, pc} if (IS_NOEVENT(record.event) || pre_process_record_quantum(&record)) { mov r0, r4 bl cmp r0, #0 bne.n b.n : /** \brief Allows for handling tap-hold actions immediately instead of waiting for TAPPING_TERM or another keypress. * * FIXME: Needs documentation. */ void process_record_tap_hint(keyrecord_t *record) { if (!IS_KEYEVENT(record->event)) { ldrb r3, [r0, #4] cmp r3, #1 bne.n return; } action_t action = layer_switch_get_action(record->event.key); ldrh r0, [r0, #0] b.w swap_held = true; } break; # endif } } bx lr : * * @param mouse_keycode[in] uint8_t mouse keycode * @param pressed[in] bool */ void register_mouse(uint8_t mouse_keycode, bool pressed) { push {r3, lr} #ifdef MOUSEKEY_ENABLE // if mousekeys is enabled, let it do the brunt of the work if (pressed) { cbz r1, mousekey_on(mouse_keycode); bl if (KC_MS_BTN1 <= mouse_keycode && mouse_keycode <= KC_MS_BTN3) { uint8_t tmp_button_msk = MOUSE_BTN_MASK(mouse_keycode - KC_MS_BTN1); tp_buttons = pressed ? tp_buttons | tmp_button_msk : tp_buttons & ~tmp_button_msk; } #endif } ldmia.w sp!, {r3, lr} mousekey_send(); b.w mousekey_off(mouse_keycode); bl b.n : /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. */ __attribute__((weak)) void register_code(uint8_t code) { push {r4, lr} if (code == KC_NO) { mov r4, r0 cmp r0, #0 beq.n return; #ifdef LOCKING_SUPPORT_ENABLE } else if (KC_LOCKING_CAPS_LOCK == code) { cmp r0, #130 @ 0x82 bne.n # ifdef LOCKING_RESYNC_ENABLE // Resync: ignore if caps lock already is on if (host_keyboard_led_state().caps_lock) return; bl lsls r1, r0, #30 bmi.n void send_keyboard_report(void); /* key */ inline void add_key(uint8_t key) { add_key_to_report(key); movs r0, #57 @ 0x39 bl # endif add_key(KC_CAPS_LOCK); send_keyboard_report(); bl wait_ms(TAP_HOLD_CAPS_DELAY); mov.w r0, #800 @ 0x320 bl } inline void del_key(uint8_t key) { del_key_from_report(key); movs r0, #57 @ 0x39 bl #endif } else if (IS_MOUSE_KEYCODE(code)) { register_mouse(code, true); } } ldmia.w sp!, {r4, lr} send_keyboard_report(); b.w } else if (KC_LOCKING_NUM_LOCK == code) { cmp r0, #131 @ 0x83 bne.n if (host_keyboard_led_state().num_lock) return; bl lsls r2, r0, #31 bmi.n add_key_to_report(key); movs r0, #83 @ 0x53 bl send_keyboard_report(); bl wait_ms(100); mov.w r0, #1000 @ 0x3e8 bl del_key_from_report(key); movs r0, #83 @ 0x53 b.n } else if (KC_LOCKING_SCROLL_LOCK == code) { cmp r0, #132 @ 0x84 bne.n if (host_keyboard_led_state().scroll_lock) return; bl lsls r3, r0, #29 bmi.n add_key_to_report(key); movs r0, #71 @ 0x47 bl send_keyboard_report(); bl wait_ms(100); mov.w r0, #1000 @ 0x3e8 bl del_key_from_report(key); movs r0, #71 @ 0x47 b.n } else if (IS_BASIC_KEYCODE(code)) { subs r3, r0, #4 uxtb r3, r3 cmp r3, #160 @ 0xa0 bhi.n if (is_key_pressed(code)) { bl cbz r0, mov r0, r4 bl send_keyboard_report(); bl add_key_to_report(key); mov r0, r4 bl send_keyboard_report(); b.n } else if (IS_MODIFIER_KEYCODE(code)) { add.w r3, r0, #32 uxtb r3, r3 cmp r3, #7 bhi.n add_mods(MOD_BIT(code)); and.w r4, r0, #7 movs r0, #1 lsls r0, r4 uxtb r0, r0 bl send_keyboard_report(); b.n } else if (IS_SYSTEM_KEYCODE(code)) { add.w r3, r0, #91 @ 0x5b uxtb r3, r3 cmp r3, #2 bhi.n host_system_send(KEYCODE2SYSTEM(code)); subs r0, #36 @ 0x24 } ldmia.w sp!, {r4, lr} host_system_send(KEYCODE2SYSTEM(code)); uxth r0, r0 b.w } else if (IS_CONSUMER_KEYCODE(code)) { add.w r3, r0, #88 @ 0x58 uxtb r3, r3 cmp r3, #26 bhi.n host_consumer_send(KEYCODE2CONSUMER(code)); ldr r2, [pc, #36] @ () } ldmia.w sp!, {r4, lr} host_consumer_send(KEYCODE2CONSUMER(code)); ldrh.w r0, [r2, r3, lsl #1] b.w } else if (IS_MOUSE_KEYCODE(code)) { adds r4, #51 @ 0x33 uxtb r4, r4 cmp r4, #18 bhi.n mousekey_on(mouse_keycode); bl } ldmia.w sp!, {r4, lr} mousekey_send(); b.w } pop {r4, pc} nop .word 0x60008ae6 : /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. */ __attribute__((weak)) void unregister_code(uint8_t code) { push {r3, lr} if (code == KC_NO) { mov r3, r0 cmp r0, #0 beq.n return; #ifdef LOCKING_SUPPORT_ENABLE } else if (KC_LOCKING_CAPS_LOCK == code) { cmp r0, #130 @ 0x82 bne.n # ifdef LOCKING_RESYNC_ENABLE // Resync: ignore if caps lock already is off if (!host_keyboard_led_state().caps_lock) return; bl lsls r1, r0, #30 bpl.n movs r0, #57 @ 0x39 bl # endif add_key(KC_CAPS_LOCK); send_keyboard_report(); bl del_key_from_report(key); movs r0, #57 @ 0x39 bl #endif } else if (IS_MOUSE_KEYCODE(code)) { register_mouse(code, false); } } ldmia.w sp!, {r3, lr} send_keyboard_report(); b.w } else if (KC_LOCKING_NUM_LOCK == code) { cmp r0, #131 @ 0x83 bne.n if (!host_keyboard_led_state().num_lock) return; bl lsls r2, r0, #31 bpl.n add_key_to_report(key); movs r0, #83 @ 0x53 bl send_keyboard_report(); bl del_key_from_report(key); movs r0, #83 @ 0x53 b.n } else if (KC_LOCKING_SCROLL_LOCK == code) { cmp r0, #132 @ 0x84 bne.n if (!host_keyboard_led_state().scroll_lock) return; bl lsls r3, r0, #29 bpl.n add_key_to_report(key); movs r0, #71 @ 0x47 bl send_keyboard_report(); bl del_key_from_report(key); movs r0, #71 @ 0x47 b.n } else if (IS_BASIC_KEYCODE(code)) { subs r2, r0, #4 uxtb r2, r2 cmp r2, #160 @ 0xa0 bls.n } else if (IS_MODIFIER_KEYCODE(code)) { add.w r2, r0, #32 uxtb r2, r2 cmp r2, #7 bhi.n del_mods(MOD_BIT(code)); and.w r3, r0, #7 movs r0, #1 lsls r0, r3 uxtb r0, r0 bl send_keyboard_report(); b.n } else if (IS_SYSTEM_KEYCODE(code)) { add.w r2, r0, #91 @ 0x5b uxtb r2, r2 cmp r2, #2 bhi.n } ldmia.w sp!, {r3, lr} host_system_send(0); movs r0, #0 b.w } else if (IS_CONSUMER_KEYCODE(code)) { add.w r2, r0, #88 @ 0x58 uxtb r2, r2 cmp r2, #26 bhi.n } ldmia.w sp!, {r3, lr} host_consumer_send(0); movs r0, #0 b.w } else if (IS_MOUSE_KEYCODE(code)) { adds r3, #51 @ 0x33 uxtb r3, r3 cmp r3, #18 bhi.n mousekey_off(mouse_keycode); bl } ldmia.w sp!, {r3, lr} mousekey_send(); b.w } pop {r3, pc} : /** \brief Tap a keycode with a delay. * * \param code The basic keycode to tap. * \param delay The amount of time in milliseconds to leave the keycode registered, before unregistering it. */ __attribute__((weak)) void tap_code_delay(uint8_t code, uint16_t delay) { push {r3, r4, r5, lr} mov r5, r0 mov r4, r1 register_code(code); bl for (uint16_t i = delay; i > 0; i--) { cbnz r4, wait_ms(1); } unregister_code(code); mov r0, r5 bl } pop {r3, r4, r5, pc} wait_ms(1); movs r0, #10 for (uint16_t i = delay; i > 0; i--) { subs r4, #1 wait_ms(1); bl for (uint16_t i = delay; i > 0; i--) { uxth r4, r4 b.n : /** \brief Tap a keycode with the default delay. * * \param code The basic keycode to tap. If `code` is `KC_CAPS_LOCK`, the delay will be `TAP_HOLD_CAPS_DELAY`, otherwise `TAP_CODE_DELAY`, if defined. */ __attribute__((weak)) void tap_code(uint8_t code) { push {r3, lr} tap_code_delay(code, code == KC_CAPS_LOCK ? TAP_HOLD_CAPS_DELAY : TAP_CODE_DELAY); cmp r0, #57 @ 0x39 ite eq moveq r1, #80 @ 0x50 movne r1, #0 bl } pop {r3, pc} : /** \brief Adds the given physically pressed modifiers and sends a keyboard report immediately. * * \param mods A bitfield of modifiers to register. */ __attribute__((weak)) void register_mods(uint8_t mods) { push {r3, lr} if (mods) { cbz r0, add_mods(mods); bl send_keyboard_report(); } } ldmia.w sp!, {r3, lr} send_keyboard_report(); b.w } pop {r3, pc} : /** \brief Removes the given physically pressed modifiers and sends a keyboard report immediately. * * \param mods A bitfield of modifiers to unregister. */ __attribute__((weak)) void unregister_mods(uint8_t mods) { push {r3, lr} if (mods) { cbz r0, del_mods(mods); bl send_keyboard_report(); } } ldmia.w sp!, {r3, lr} send_keyboard_report(); b.w } pop {r3, pc} : void process_action(keyrecord_t *record, action_t action) { stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} uint8_t tap_count = record->tap.count; ldrb r7, [r0, #6] keyevent_t event = record->event; ldrb r5, [r0, #5] void process_action(keyrecord_t *record, action_t action) { mov r8, r0 mov r4, r1 if (is_oneshot_layer_active() && event.pressed && bl uint8_t tap_count = record->tap.count; lsrs r7, r7, #4 if (is_oneshot_layer_active() && event.pressed && mov r6, r0 cbz r0, mov r6, r5 cbz r5, (action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code) ubfx r3, r4, #8, #8 if (is_oneshot_layer_active() && event.pressed && and.w r2, r3, #240 @ 0xf0 cmp r2, #64 @ 0x40 beq.n (action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code) uxtb r1, r4 add.w r2, r1, #32 uxtb r2, r2 cmp r2, #7 bls.n and.w r3, r3, #224 @ 0xe0 cmp r3, #32 bne.n || ((action.kind.id == ACT_LMODS_TAP || action.kind.id == ACT_RMODS_TAP) && (action.layer_tap.code <= MODS_TAP_TOGGLE || tap_count == 0)) cmp r1, #1 bls.n cbz r7, && keymap_config.oneshot_enable) { ldr r3, [pc, #660] @ () ldrb r6, [r3, #1] ands.w r6, r6, #4 beq.n clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); movs r0, #2 bl do_release_oneshot = !is_oneshot_layer_active(); bl eor.w r6, r0, #1 uxtb r6, r6 switch (action.kind.id) { ubfx r3, r4, #12, #4 cmp r3, #11 bhi.n tbh [pc, r3, lsl #1] .short 0x0010 .word 0x00540010 .word 0x00ae0054 .word 0x003c00c5 .word 0x00ca003c .word 0x0142012d .short 0x0142 bool do_release_oneshot = false; movs r6, #0 b.n mov r6, r7 b.n uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods : action.key.mods << 4; ubfx r3, r4, #8, #8 ubfx r7, r4, #8, #4 cmp r3, #15 it hi lslhi r7, r7, #4 (action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code) uxtb r4, r4 if (event.pressed) { cbz r5, if (mods) { cbz r7, if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) { add.w r3, r4, #32 uxtb r3, r3 cmp r3, #7 add_mods(mods); mov r0, r7 if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) { bls.n cbnz r4, add_mods(mods); bl send_keyboard_report(); bl register_code(action.key.code); mov r0, r4 b.n add_weak_mods(mods); bl b.n unregister_code(action.key.code); mov r0, r4 bl if (mods) { cbz r7, if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) { add.w r3, r4, #32 uxtb r3, r3 cmp r3, #7 del_mods(mods); mov r0, r7 if (IS_MODIFIER_KEYCODE(action.key.code) || action.key.code == KC_NO) { bls.n cbnz r4, del_mods(mods); bl b.n del_weak_mods(mods); bl send_keyboard_report(); bl if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED)) { cmp r6, #0 beq.w bl ands.w r0, r0, #1 bne.w record->event.pressed = false; strb.w r0, [r8, #5] layer_on(get_oneshot_layer()); bl bl process_record(record); mov r0, r8 bl layer_off(get_oneshot_layer()); bl } ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, lr} layer_off(get_oneshot_layer()); b.w uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; ubfx r3, r4, #8, #8 and.w r3, r3, #240 @ 0xf0 ubfx r9, r4, #8, #4 cmp r3, #32 switch (action.layer_tap.code) { uxtb r4, r4 uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods : action.key.mods << 4; it ne movne.w r9, r9, lsl #4 switch (action.layer_tap.code) { cbz r4, cmp r4, #1 beq.n if (event.pressed) { cmp r5, #0 beq.n if (tap_count > 0) { cbz r7, b.n if (!keymap_config.oneshot_enable) { ldr r3, [pc, #420] @ () ldrb r3, [r3, #1] lsls r0, r3, #29 bmi.n if (event.pressed) { cbz r5, if (mods) { cmp.w r9, #0 beq.n add_mods(mods); mov r0, r9 bl send_keyboard_report(); bl register_code(action.key.code); movs r0, #0 register_code(action.key.code); bl switch (action.kind.id) { b.n unregister_code(action.key.code); mov r0, r5 bl if (mods) { cmp.w r9, #0 beq.n del_mods(mods); mov r0, r9 b.n if (event.pressed) { cbz r5, if (tap_count == 0) { cbnz r7, register_mods(mods); mov r0, r9 bl switch (action.kind.id) { b.n } else if (tap_count == 1) { cmp r7, #1 bne.n add_oneshot_mods(mods); mov r0, r9 bl switch (action.kind.id) { b.n if (tap_count == 0) { cmp r7, #0 bne.n unregister_mods(mods); mov r0, r9 bl del_oneshot_mods(mods); mov r0, r9 bl del_oneshot_locked_mods(mods); mov r0, r9 bl switch (action.kind.id) { b.n if (event.pressed) { cbz r5, if (tap_count <= TAPPING_TOGGLE) { cmp r7, #5 bhi.n b.n if (tap_count < TAPPING_TOGGLE) { cmp r7, #4 bhi.n unregister_mods(mods); mov r0, r9 bl switch (action.kind.id) { b.n if (tap_count > 0) { cmp r7, #0 beq.n if (action.layer_tap.code == KC_CAPS_LOCK) { cmp r4, #57 @ 0x39 wait_ms(TAP_HOLD_CAPS_DELAY); ite eq moveq.w r0, #800 @ 0x320 wait_ms(TAP_CODE_DELAY); movne r0, #1 bl unregister_code(action.key.code); mov r0, r4 bl switch (action.kind.id) { b.n switch (action.usage.page) { tst.w r4, #3072 @ 0xc00 ubfx r3, r4, #10, #2 beq.n cmp r3, #1 bne.n host_consumer_send(event.pressed ? action.usage.code : 0); cbz r5, ubfx r0, r4, #0, #10 bl switch (action.kind.id) { b.n host_system_send(event.pressed ? action.usage.code : 0); cbz r5, ubfx r0, r4, #0, #10 bl switch (action.kind.id) { b.n host_system_send(event.pressed ? action.usage.code : 0); mov r0, r5 b.n host_consumer_send(event.pressed ? action.usage.code : 0); mov r0, r5 b.n register_mouse(action.key.code, event.pressed); mov r1, r5 uxtb r0, r4 bl switch (action.kind.id) { b.n if (action.layer_bitop.on == 0) { tst.w r4, #768 @ 0x300 bne.n if (!event.pressed) { cbnz r5, uint8_t shift = action.layer_bitop.part * 4; ubfx r3, r4, #5, #3 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; lsls r1, r4, #27 uint8_t shift = action.layer_bitop.part * 4; mov.w r3, r3, lsl #2 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; it mi movmi r5, #15 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; uxtb r3, r3 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; it mi lslmi r5, r3 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; and.w r2, r4, #15 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; it mi mvnmi r5, r5 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; lsl.w r2, r2, r3 switch (action.layer_bitop.op) { ubfx r4, r4, #10, #2 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; it mi uxthmi r5, r5 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; uxth r2, r2 switch (action.layer_bitop.op) { cmp r4, #2 default_layer_and(bits | mask); orr.w r0, r5, r2 beq.n cmp r4, #3 beq.n cmp r4, #1 beq.n bl led_set(host_keyboard_leds()); bl bl break; b.n default_layer_or(bits | mask); bl switch (action.kind.id) { b.n default_layer_xor(bits | mask); bl switch (action.kind.id) { b.n default_layer_set(bits | mask); bl switch (action.kind.id) { b.n if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { ubfx r2, r4, #8, #2 cbz r5, lsls r2, r2, #31 bpl.n uint8_t shift = action.layer_bitop.part * 4; ubfx r3, r4, #5, #3 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; ands.w r0, r4, #16 uint8_t shift = action.layer_bitop.part * 4; mov.w r3, r3, lsl #2 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; uxtb r3, r3 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; itt ne movne r0, #15 lslne r0, r3 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; and.w r2, r4, #15 lsl.w r2, r2, r3 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; it ne mvnne r0, r0 switch (action.layer_bitop.op) { ubfx r4, r4, #10, #2 layer_state_t mask = (action.layer_bitop.xbit) ? ~(((layer_state_t)0xf) << shift) : 0; ite ne uxthne r3, r0 moveq r3, r0 layer_state_t bits = ((layer_state_t)action.layer_bitop.bits) << shift; uxth r2, r2 switch (action.layer_bitop.op) { cmp r4, #2 layer_and(bits | mask); orr.w r0, r3, r2 beq.n cmp r4, #3 beq.n cmp r4, #1 beq.n bl switch (action.kind.id) { b.n if (event.pressed ? (action.layer_bitop.on & ON_PRESS) : (action.layer_bitop.on & ON_RELEASE)) { cmp r2, #1 bls.n b.n layer_or(bits | mask); bl switch (action.kind.id) { b.n layer_xor(bits | mask); bl switch (action.kind.id) { b.n layer_state_set(bits | mask); bl switch (action.kind.id) { b.n (action.kind.id == ACT_USAGE || !(IS_MODIFIER_KEYCODE(action.key.code) uxtb r7, r4 layer_on(action.layer_mods.layer); ubfx r4, r4, #8, #4 if (event.pressed) { cbz r5, layer_on(action.layer_mods.layer); mov r0, r4 bl register_mods(action.layer_mods.mods); mov r0, r7 bl switch (action.kind.id) { b.n nop .word 0x20002048 unregister_mods(action.layer_mods.mods); mov r0, r7 bl layer_off(action.layer_mods.layer); mov r0, r4 layer_off(action.layer_tap.val); bl switch (action.kind.id) { b.n switch (action.layer_tap.code) { uxtb.w r9, r4 sub.w r3, r9, #240 @ 0xf0 cmp r3, #4 bhi.n tbb [pc, r3] .short 0x2103 .short 0x140d .byte 0x1d .byte 0x00 if (event.pressed) { cbz r5, if (tap_count < TAPPING_TOGGLE) { cmp r7, #4 bhi.n layer_invert(action.layer_tap.val); ubfx r0, r4, #8, #5 bl switch (action.kind.id) { b.n if (tap_count <= TAPPING_TOGGLE) { cmp r7, #5 b.n event.pressed ? layer_off(action.layer_tap.val) : layer_on(action.layer_tap.val); ubfx r0, r4, #8, #5 cmp r5, #0 bne.n layer_on(action.layer_tap.val); bl switch (action.kind.id) { b.n event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); cbz r5, ubfx r0, r4, #8, #5 bl switch (action.kind.id) { b.n event.pressed ? layer_move(action.layer_tap.val) : layer_clear(); bl switch (action.kind.id) { b.n if (!keymap_config.oneshot_enable) { ldr r3, [pc, #112] @ () ldrb r3, [r3, #1] lsls r3, r3, #29 bmi.n layer_on(action.layer_tap.val); ubfx r0, r4, #8, #5 if (event.pressed) { cmp r5, #0 beq.n b.n if (event.pressed) { cbz r5, layer_on(action.layer_tap.val); ubfx r4, r4, #8, #5 mov r0, r4 bl set_oneshot_layer(action.layer_tap.val, ONESHOT_START); movs r1, #3 mov r0, r4 bl switch (action.kind.id) { b.n clear_oneshot_layer_state(ONESHOT_PRESSED); movs r0, #1 bl if (tap_count > 1) { cmp r7, #1 bls.w clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); movs r0, #2 bl switch (action.kind.id) { b.n if (event.pressed) { cbz r5, if (tap_count > 0) { cbz r7, register_code(action.layer_tap.code); mov r0, r9 bl switch (action.kind.id) { b.n layer_on(action.layer_tap.val); ubfx r0, r4, #8, #5 b.n if (tap_count > 0) { cbz r7, if (action.layer_tap.code == KC_CAPS_LOCK) { cmp.w r9, #57 @ 0x39 wait_ms(TAP_HOLD_CAPS_DELAY); ite eq moveq.w r0, #800 @ 0x320 wait_ms(TAP_CODE_DELAY); movne r0, #1 bl unregister_code(action.layer_tap.code); mov r0, r9 bl switch (action.kind.id) { b.n layer_off(action.layer_tap.val); ubfx r0, r4, #8, #5 b.n } ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} nop .word 0x20002048 : void process_record_handler(keyrecord_t *record) { push {r3, r4, r5, lr} action_t action = store_or_get_action(record->event.pressed, record->event.key); ldrh r1, [r0, #0] void process_record_handler(keyrecord_t *record) { mov r4, r0 action_t action = store_or_get_action(record->event.pressed, record->event.key); ldrb r0, [r0, #5] bl mov r5, r0 layer_debug(); bl default_layer_debug(); bl process_action(record, action); mov r1, r5 mov r0, r4 } ldmia.w sp!, {r3, r4, r5, lr} process_action(record, action); b.w ... : if (IS_NOEVENT(record->event)) { ldrb r3, [r0, #4] void process_record(keyrecord_t *record) { push {r4, lr} mov r4, r0 if (IS_NOEVENT(record->event)) { cbz r3, if (!process_record_quantum(record)) { bl cbnz r0, if (is_oneshot_layer_active() && record->event.pressed && keymap_config.oneshot_enable) { bl cbz r0, ldrb r3, [r4, #5] cbz r3, ldr r3, [pc, #28] @ () ldrb r3, [r3, #1] lsls r3, r3, #29 bpl.n } ldmia.w sp!, {r4, lr} clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); movs r0, #2 b.w process_record_handler(record); mov r0, r4 bl post_process_record_quantum(record); mov r0, r4 bl } pop {r4, pc} .word 0x20002048 : /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. */ void clear_keyboard_but_mods_and_keys(void) { push {r3, lr} #ifdef EXTRAKEY_ENABLE host_system_send(0); movs r0, #0 bl host_consumer_send(0); movs r0, #0 bl #endif clear_weak_mods(); bl send_keyboard_report(); bl #ifdef MOUSEKEY_ENABLE mousekey_clear(); bl mousekey_send(); #endif #ifdef PROGRAMMABLE_BUTTON_ENABLE programmable_button_clear(); #endif } ldmia.w sp!, {r3, lr} mousekey_send(); b.w : void clear_keyboard_but_mods(void) { push {r3, lr} } inline void clear_keys(void) { clear_keys_from_report(); bl } ldmia.w sp!, {r3, lr} clear_keyboard_but_mods_and_keys(); b.w : void clear_keyboard(void) { push {r3, lr} clear_mods(); bl } ldmia.w sp!, {r3, lr} clear_keyboard_but_mods(); b.w : /** \brief Utilities for actions. (FIXME: Needs better description) * * FIXME: Needs documentation. */ bool is_tap_action(action_t action) { switch (action.kind.id) { ubfx r3, r0, #12, #4 cmp r3, #6 uxtb r2, r0 beq.n ite ls addls r3, #14 addhi r3, #6 and.w r3, r3, #15 cmp r3, #1 bhi.n case ACT_LMODS_TAP: case ACT_RMODS_TAP: case ACT_LAYER_TAP: case ACT_LAYER_TAP_EXT: switch (action.layer_tap.code) { cmp r2, #240 @ 0xf0 beq.n bhi.n cmp r2, #231 @ 0xe7 ite hi movhi r0, #0 movls r0, #1 bx lr cmp r2, #244 @ 0xf4 ite ne movne r0, #0 moveq r0, #1 bx lr case OP_ONESHOT: return true; } return false; case ACT_SWAP_HANDS: switch (action.swap.code) { cmp r2, #231 @ 0xe7 bls.n cmp r2, #241 @ 0xf1 b.n switch (action.kind.id) { movs r0, #0 bx lr return true; movs r0, #1 return true; } return false; } return false; } bx lr : bool is_tap_record(keyrecord_t *record) { push {r3, lr} mov r3, r0 if (IS_NOEVENT(record->event)) { ldrb r0, [r0, #4] cbz r0, action_t action = layer_switch_get_action(record->event.key); ldrh r0, [r3, #0] bl } ldmia.w sp!, {r3, lr} return is_tap_action(action); b.w } pop {r3, pc} : /** \brief Debug print (FIXME: Needs better description) * * FIXME: Needs documentation. */ void debug_event(keyevent_t event) { sub sp, #8 add r3, sp, #8 stmdb r3, {r0, r1} ac_dprintf("%04X%c(%u)", (event.key.row << 8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); } add sp, #8 bx lr : /** \brief Debug print (FIXME: Needs better description) * * FIXME: Needs documentation. */ void debug_record(keyrecord_t record) { sub sp, #8 add r3, sp, #8 stmdb r3, {r0, r1} debug_event(record.event); #ifndef NO_ACTION_TAPPING ac_dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); #endif } add sp, #8 bx lr : * * Run user code on default layer state change */ __attribute__((weak)) layer_state_t default_layer_state_set_user(layer_state_t state) { return state; } bx lr : /** \brief Default Layer State Set At Keyboard Level * * Run keyboard code on default layer state change */ __attribute__((weak)) layer_state_t default_layer_state_set_kb(layer_state_t state) { push {r3, lr} return default_layer_state_set_user(state); bl } pop {r3, pc} ... : /** \brief Default Layer State Set * * Static function to set the default layer state, prints debug info and clears keys */ static void default_layer_state_set(layer_state_t state) { push {r3, lr} state = default_layer_state_set_kb(state); bl ac_dprintf("default_layer_state: "); default_layer_debug(); ac_dprintf(" to "); default_layer_state = state; ldr r3, [pc, #4] @ () strh r0, [r3, #0] #if defined(STRICT_LAYER_RELEASE) clear_keyboard_but_mods(); // To avoid stuck keys #elif defined(SEMI_STRICT_LAYER_RELEASE) clear_keyboard_but_mods_and_keys(); // Don't reset held keys #endif } pop {r3, pc} .word 0x20001044 : * * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit. */ void default_layer_debug(void) { ac_dprintf("%08hX(%u)", default_layer_state, get_highest_layer(default_layer_state)); } bx lr : /** \brief Default Layer Set * * Sets the default layer state. */ void default_layer_set(layer_state_t state) { default_layer_state_set(state); b.w ... : /** \brief Default Layer Or * * Turns on the default layer based on matching bits between specified layer and existing layer state */ void default_layer_or(layer_state_t state) { default_layer_state_set(default_layer_state | state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] orrs r0, r3 b.w nop .word 0x20001044 : /** \brief Default Layer And * * Turns on default layer based on matching enabled bits between specified layer and existing layer state */ void default_layer_and(layer_state_t state) { default_layer_state_set(default_layer_state & state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] ands r0, r3 b.w nop .word 0x20001044 : /** \brief Default Layer Xor * * Turns on default layer based on non-matching bits between specified layer and existing layer state */ void default_layer_xor(layer_state_t state) { default_layer_state_set(default_layer_state ^ state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] eors r0, r3 b.w nop .word 0x20001044 : /** \brief Layer state set user * * Runs user code on layer state change */ __attribute__((weak)) layer_state_t layer_state_set_user(layer_state_t state) { bx lr : /** \brief Layer state set keyboard * * Runs keyboard code on layer state change */ __attribute__((weak)) layer_state_t layer_state_set_kb(layer_state_t state) { push {r3, lr} return layer_state_set_user(state); bl } pop {r3, pc} ... : /** \brief Layer state set * * Sets the layer to match the specified state (a bitmask) */ void layer_state_set(layer_state_t state) { push {r3, lr} state = layer_state_set_kb(state); bl ac_dprintf("layer_state: "); layer_debug(); ac_dprintf(" to "); layer_state = state; ldr r3, [pc, #4] @ () strh r0, [r3, #0] # if defined(STRICT_LAYER_RELEASE) clear_keyboard_but_mods(); // To avoid stuck keys # elif defined(SEMI_STRICT_LAYER_RELEASE) clear_keyboard_but_mods_and_keys(); // Don't reset held keys # endif } pop {r3, pc} .word 0x20001042 : /** \brief Layer clear * * Turn off all layers */ void layer_clear(void) { layer_state_set(0); movs r0, #0 b.w : /** \brief Layer move * * Turns on the given layer and turn off all other layers */ void layer_move(uint8_t layer) { layer_state_set((layer_state_t)1 << layer); movs r3, #1 lsl.w r0, r3, r0 uxth r0, r0 b.w ... : /** \brief Layer on * * Turns on given layer */ void layer_on(uint8_t layer) { layer_state_set(layer_state | ((layer_state_t)1 << layer)); movs r3, #1 lsl.w r0, r3, r0 ldr r3, [pc, #12] @ () ldrh r3, [r3, #0] orrs r0, r3 uxth r0, r0 b.w nop .word 0x20001042 : /** \brief Layer off * * Turns off given layer */ void layer_off(uint8_t layer) { layer_state_set(layer_state & ~((layer_state_t)1 << layer)); ldr r2, [pc, #12] @ () movs r3, #1 lsls r3, r0 ldrh r0, [r2, #0] bic.w r0, r0, r3 b.w .word 0x20001042 : /** \brief Layer invert * * Toggle the given layer (set it if it's unset, or unset it if it's set) */ void layer_invert(uint8_t layer) { layer_state_set(layer_state ^ ((layer_state_t)1 << layer)); movs r3, #1 lsl.w r0, r3, r0 ldr r3, [pc, #12] @ () ldrh r3, [r3, #0] eors r0, r3 uxth r0, r0 b.w nop .word 0x20001042 : /** \brief Layer or * * Turns on layers based on matching bits between specified layer and existing layer state */ void layer_or(layer_state_t state) { layer_state_set(layer_state | state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] orrs r0, r3 b.w nop .word 0x20001042 : /** \brief Layer and * * Turns on layers based on matching enabled bits between specified layer and existing layer state */ void layer_and(layer_state_t state) { layer_state_set(layer_state & state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] ands r0, r3 b.w nop .word 0x20001042 : /** \brief Layer xor * * Turns on layers based on non-matching bits between specified layer and existing layer state */ void layer_xor(layer_state_t state) { layer_state_set(layer_state ^ state); ldr r3, [pc, #8] @ () ldrh r3, [r3, #0] eors r0, r3 b.w nop .word 0x20001042 : /** \brief Layer debug printing * * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit. */ void layer_debug(void) { bx lr : */ void update_source_layers_cache_impl(uint8_t layer, uint16_t entry_number, uint8_t cache[][MAX_LAYER_BITS]) { const uint16_t storage_idx = entry_number / (CHAR_BIT); const uint8_t storage_bit = entry_number % (CHAR_BIT); for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { cache[storage_idx][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ cache[storage_idx][bit_number]) & (1U << storage_bit); and.w r3, r1, #7 void update_source_layers_cache_impl(uint8_t layer, uint16_t entry_number, uint8_t cache[][MAX_LAYER_BITS]) { push {r4, r5, lr} cache[storage_idx][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ cache[storage_idx][bit_number]) & (1U << storage_bit); lsrs r1, r1, #3 movs r4, #1 add.w r2, r2, r1, lsl #2 lsls r4, r3 uxtb r4, r4 subs r2, #1 movs r1, #0 ldrb.w r5, [r2, #1]! lsr.w r3, r0, r1 sbfx r3, r3, #0, #1 eors r3, r5 ands r3, r4 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { adds r1, #1 cache[storage_idx][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ cache[storage_idx][bit_number]) & (1U << storage_bit); eors r5, r3 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { cmp r1, #4 cache[storage_idx][bit_number] ^= (-((layer & (1U << bit_number)) != 0) ^ cache[storage_idx][bit_number]) & (1U << storage_bit); strb r5, [r2, #0] for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { bne.n } } pop {r4, r5, pc} : /** \brief read source layers cache * * reads the cached keys stored when the layer was changed */ uint8_t read_source_layers_cache_impl(uint16_t entry_number, uint8_t cache[][MAX_LAYER_BITS]) { push {r4, lr} const uint16_t storage_idx = entry_number / (CHAR_BIT); const uint8_t storage_bit = entry_number % (CHAR_BIT); uint8_t layer = 0; for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { layer |= ((cache[storage_idx][bit_number] & (1U << storage_bit)) != 0) << bit_number; movs r2, #0 const uint8_t storage_bit = entry_number % (CHAR_BIT); and.w r4, r0, #7 layer |= ((cache[storage_idx][bit_number] & (1U << storage_bit)) != 0) << bit_number; lsrs r0, r0, #3 add.w r1, r1, r0, lsl #2 uint8_t layer = 0; mov r0, r2 layer |= ((cache[storage_idx][bit_number] & (1U << storage_bit)) != 0) << bit_number; ldrb r3, [r1, r2] lsrs r3, r4 and.w r3, r3, #1 lsls r3, r2 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { adds r2, #1 layer |= ((cache[storage_idx][bit_number] & (1U << storage_bit)) != 0) << bit_number; orrs r0, r3 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { cmp r2, #4 layer |= ((cache[storage_idx][bit_number] & (1U << storage_bit)) != 0) << bit_number; uxtb r0, r0 for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { bne.n } return layer; } pop {r4, pc} ... : /** \brief update encoder source layers cache * * Updates the cached encoders when changing layers */ void update_source_layers_cache(keypos_t key, uint8_t layer) { push {r0, r1, r2, r4} strh.w r0, [sp, #4] ubfx r0, r0, #8, #8 if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) { cmp r0, #14 void update_source_layers_cache(keypos_t key, uint8_t layer) { mov r4, r1 if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) { bhi.n ldrb.w r3, [sp, #4] cmp r3, #6 bhi.n const uint16_t entry_number = (uint16_t)(key.row * MATRIX_COLS) + key.col; rsb r0, r0, r0, lsl #3 add r3, r0 update_source_layers_cache_impl(layer, entry_number, source_layers_cache); ldr r2, [pc, #20] @ () uxth r1, r3 mov r0, r4 else if (key.row == KEYLOC_ENCODER_CW || key.row == KEYLOC_ENCODER_CCW) { const uint16_t entry_number = key.col; update_source_layers_cache_impl(layer, entry_number, encoder_source_layers_cache); } # endif // ENCODER_MAP_ENABLE } add sp, #12 pop {r4} update_source_layers_cache_impl(layer, entry_number, source_layers_cache); b.w } add sp, #12 pop {r4} bx lr nop .word 0x20001009 : /** \brief read source layers cache * * reads the cached keys stored when the layer was changed */ uint8_t read_source_layers_cache(keypos_t key) { sub sp, #8 strh.w r0, [sp, #4] ubfx r0, r0, #8, #8 if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) { cmp r0, #14 bhi.n ldrb.w r3, [sp, #4] cmp r3, #6 bhi.n const uint16_t entry_number = (uint16_t)(key.row * MATRIX_COLS) + key.col; rsb r0, r0, r0, lsl #3 add r0, r3 return read_source_layers_cache_impl(entry_number, source_layers_cache); ldr r1, [pc, #12] @ () uxth r0, r0 const uint16_t entry_number = key.col; return read_source_layers_cache_impl(entry_number, encoder_source_layers_cache); } # endif // ENCODER_MAP_ENABLE return 0; } add sp, #8 return read_source_layers_cache_impl(entry_number, source_layers_cache); b.w } movs r0, #0 add sp, #8 bx lr .word 0x20001009 : uint8_t layer_switch_get_layer(keypos_t key) { #ifndef NO_ACTION_LAYER action_t action; action.code = ACTION_TRANSPARENT; layer_state_t layers = layer_state | default_layer_state; ldr r3, [pc, #56] @ () uint8_t layer_switch_get_layer(keypos_t key) { push {r0, r1, r4, r5, r6, lr} layer_state_t layers = layer_state | default_layer_state; ldrh r5, [r3, #0] ldr r3, [pc, #56] @ () uint8_t layer_switch_get_layer(keypos_t key) { strh.w r0, [sp, #4] layer_state_t layers = layer_state | default_layer_state; ldrh r3, [r3, #0] orrs r5, r3 uxth r5, r5 movs r4, #15 /* check top layer first */ for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { if (layers & ((layer_state_t)1 << i)) { asr.w r3, r5, r4 lsls r3, r3, #31 bmi.n for (int8_t i = MAX_LAYER - 1; i >= 0; i--) { subs r4, #1 bcs.n return i; } } } /* fall back to layer 0 */ return 0; movs r6, #0 #else return get_highest_layer(default_layer_state); #endif } mov r0, r6 add sp, #8 pop {r4, r5, r6, pc} uxtb r6, r4 action = action_for_key(i, key); ldr r1, [sp, #4] mov r0, r6 bl if (action.code != ACTION_TRANSPARENT) { uxth r0, r0 cmp r0, #1 beq.n b.n nop .word 0x20001042 .word 0x20001044 : /** \brief Layer switch get layer * * Gets action code based on key position */ action_t layer_switch_get_action(keypos_t key) { push {r0, r1, r2, lr} strh.w r0, [sp, #4] return action_for_key(layer_switch_get_layer(key), key); ldr r0, [sp, #4] bl ldr r1, [sp, #4] } add sp, #12 ldr.w lr, [sp], #4 return action_for_key(layer_switch_get_layer(key), key); b.w : action_t store_or_get_action(bool pressed, keypos_t key) { push {r0, r1, r4, lr} if (disable_action_cache) { ldr r3, [pc, #64] @ () action_t store_or_get_action(bool pressed, keypos_t key) { strh.w r1, [sp, #4] if (disable_action_cache) { ldrb r3, [r3, #0] cbz r3, return layer_switch_get_action(key); ldr r0, [sp, #4] } add sp, #8 ldmia.w sp!, {r4, lr} return layer_switch_get_action(key); b.w if (pressed) { cbz r0, layer = layer_switch_get_layer(key); ldr r0, [sp, #4] bl mov r4, r0 update_source_layers_cache(key, layer); mov r1, r0 ldr r0, [sp, #4] bl return action_for_key(layer, key); ldr r1, [sp, #4] mov r0, r4 } add sp, #8 ldmia.w sp!, {r4, lr} return action_for_key(layer, key); b.w layer = read_source_layers_cache(key); ldr r0, [sp, #4] bl mov r4, r0 b.n nop .word 0x20001008 : /** \brief Waiting buffer debug print * * FIXME: Needs docs */ static void debug_waiting_buffer(void) { push {r3, r4, r5, r6, r7, lr} ac_dprintf("{ "); for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { ldr r3, [pc, #48] @ () ldr r6, [pc, #48] @ () ldrb r4, [r3, #0] ac_dprintf("[%u]=", i); debug_record(waiting_buffer[i]); ldr r5, [pc, #48] @ () for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { ldrb r3, [r6, #0] cmp r3, r4 bne.n ac_dprintf(" "); } ac_dprintf("}\n"); } pop {r3, r4, r5, r6, r7, pc} debug_record(waiting_buffer[i]); add.w r3, r5, r4, lsl #3 ldrh.w r0, [r5, r4, lsl #3] ldrh r7, [r3, #2] ldrh r2, [r3, #4] ldrh r1, [r3, #6] orr.w r0, r0, r7, lsl #16 orr.w r1, r2, r1, lsl #16 for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { adds r4, #1 debug_record(waiting_buffer[i]); bl for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { and.w r4, r4, #7 b.n .word 0x20001046 .word 0x20001047 .word 0x20001048 : debug_record(tapping_key); ldr r3, [pc, #24] @ () static void debug_tapping_key(void) { push {r4} debug_record(tapping_key); ldrh r0, [r3, #0] ldrh r4, [r3, #2] ldrh r2, [r3, #4] ldrh r1, [r3, #6] orr.w r0, r0, r4, lsl #16 orr.w r1, r2, r1, lsl #16 } pop {r4} debug_record(tapping_key); b.w nop .word 0x20001088 : if ((tapping_key.tap.count > 0) || !tapping_key.event.pressed) { ldr r0, [pc, #108] @ () void waiting_buffer_scan_tap(void) { push {r3, r4, r5, r6, r7, lr} if ((tapping_key.tap.count > 0) || !tapping_key.event.pressed) { ldrb r3, [r0, #6] cmp r3, #15 bhi.n ldrb r3, [r0, #5] cbz r3, for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { ldr r3, [pc, #100] @ () ldr r2, [pc, #100] @ () ldrb r3, [r3, #0] ldrb r5, [r2, #0] if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && ( ldrh r6, [r0, #0] WITHIN_TAPPING_TERM(waiting_buffer[i].event) || MAYBE_RETRO_SHIFTING(waiting_buffer[i].event, &tapping_key) ldrh r7, [r0, #2] keyrecord_t *candidate = &waiting_buffer[i]; ldr r4, [pc, #96] @ () for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { cmp r3, r5 bne.n } pop {r3, r4, r5, r6, r7, pc} keyrecord_t *candidate = &waiting_buffer[i]; add.w r1, r4, r3, lsl #3 sxth r2, r3 if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && ( ldrb r1, [r1, #4] cbz r1, ldrh.w r2, [r4, r2, lsl #3] cmp r2, r6 bne.n add.w r1, r4, r3, lsl #3 ldrb r2, [r1, #5] cbnz r2, WITHIN_TAPPING_TERM(waiting_buffer[i].event) || MAYBE_RETRO_SHIFTING(waiting_buffer[i].event, &tapping_key) ldrh r2, [r1, #2] subs r2, r2, r7 if (IS_EVENT(candidate->event) && KEYEQ(candidate->event.key, tapping_key.event.key) && !candidate->event.pressed && ( uxth r2, r2 cmp r2, #199 @ 0xc7 bhi.n tapping_key.tap.count = 1; ldrb r3, [r0, #6] movs r2, #1 bfi r3, r2, #4, #4 strb r3, [r0, #6] candidate->tap.count = 1; ldrb r3, [r1, #6] process_record(&tapping_key); ldr r0, [pc, #28] @ () candidate->tap.count = 1; bfi r3, r2, #4, #4 strb r3, [r1, #6] process_record(&tapping_key); bl } ldmia.w sp!, {r3, r4, r5, r6, r7, lr} debug_waiting_buffer(); b.w for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { adds r3, #1 and.w r3, r3, #7 b.n nop .word 0x20001088 .word 0x20001046 .word 0x20001047 .word 0x20001048 : bool waiting_buffer_typed(keyevent_t event) { push {r4, r5, r6, r7, lr} for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { ldr r3, [pc, #52] @ () ldr r4, [pc, #52] @ () ldrb r3, [r3, #0] ldrb r6, [r4, #0] if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { ldr r4, [pc, #52] @ () for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { cmp r3, r6 bne.n return false; movs r0, #0 } pop {r4, r5, r6, r7, pc} if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) { add.w r5, r4, r3, lsl #3 ldrb r7, [r5, #1] cmp r7, r1 bne.n ldrb.w r7, [r4, r3, lsl #3] cmp r7, r0 bne.n ldrb r5, [r5, #5] cmp r5, r2 bne.n for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) { adds r3, #1 and.w r3, r3, #7 b.n return true; movs r0, #1 b.n .word 0x20001046 .word 0x20001047 .word 0x20001048 : bool process_tapping(keyrecord_t *keyp) { stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} if (IS_NOEVENT(tapping_key.event)) { ldr r5, [pc, #552] @ () const keyevent_t event = keyp->event; mov r9, sp bool process_tapping(keyrecord_t *keyp) { mov r4, r0 const keyevent_t event = keyp->event; mov r1, r0 movs r2, #6 mov r0, r9 bl if (IS_NOEVENT(tapping_key.event)) { ldrb r3, [r5, #4] const keyevent_t event = keyp->event; ldrb.w r8, [r4] ldrb r1, [r4, #1] ldrb r7, [r4, #5] ldrh.w sl, [r4, #2] ldrb r2, [r4, #4] if (IS_NOEVENT(tapping_key.event)) { cbnz r3, if (!IS_EVENT(event)) { cmp r2, #0 beq.w } else if (event.pressed && is_tap_record(keyp)) { cmp r7, #0 beq.w mov r0, r4 bl cmp r0, #0 beq.w tapping_key = *keyp; movs r2, #8 mov r1, r4 mov r0, r5 bl process_record_tap_hint(&tapping_key); mov r0, r5 bl waiting_buffer_scan_tap(); bl debug_tapping_key(); bl return true; b.n if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) { ldrh r3, [r5, #2] if (tapping_key.event.pressed) { ldrb r6, [r5, #5] if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) { sub.w r3, sl, r3 uxth r3, r3 if (tapping_key.event.pressed) { cmp r6, #0 beq.w if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) { cmp r3, #199 @ 0xc7 bhi.w if (IS_NOEVENT(event)) { cmp r2, #0 beq.w if (tapping_key.tap.count == 0) { ldrb r3, [r5, #6] if (IS_TAPPING_RECORD(keyp) && !event.pressed) { ldrh r0, [r5, #0] ldrh r2, [r4, #0] if (tapping_key.tap.count == 0) { cmp r3, #15 bhi.n if (IS_TAPPING_RECORD(keyp) && !event.pressed) { cmp r0, r2 bne.n cmp r7, #0 bne.n tapping_key.tap.count = 1; movs r2, #1 bfi r3, r2, #4, #4 strb r3, [r5, #6] debug_tapping_key(); bl process_record(&tapping_key); mov r0, r5 bl keyp->tap = tapping_key.tap; ldrb r3, [r5, #6] strb r3, [r4, #6] return false; movs r5, #0 } mov r0, r5 add sp, #16 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} !event.pressed && waiting_buffer_typed(event) && cbnz r7, mov r2, r7 mov r0, r8 bl else if (!event.pressed && !waiting_buffer_typed(event)) { mov r0, r8 bl mov r5, r0 cmp r0, #0 bne.n action_t action = layer_switch_get_action(event.key); ldr r0, [sp, #0] bl switch (action.kind.id) { ubfx r2, r0, #12, #4 cmp r2, #3 action_t action = layer_switch_get_action(event.key); uxtb r3, r0 switch (action.kind.id) { bhi.n cmp r2, #1 bls.n if (action.key.mods && keyp->tap.count == 0) return false; tst.w r0, #3840 @ 0xf00 beq.n ldrb r2, [r4, #6] cmp r2, #15 bhi.n b.n switch (action.kind.id) { adds r2, #6 and.w r2, r2, #15 cmp r2, #1 bls.n process_record(keyp); mov r0, r4 bl return true; mov r5, r6 b.n if (action.key.mods && !action.key.code) return false; tst.w r0, #3840 @ 0xf00 beq.n cmp r3, #0 beq.n if (IS_MODIFIER_KEYCODE(action.key.code)) return false; adds r3, #32 uxtb r3, r3 cmp r3, #7 bls.n b.n switch (action.layer_tap.code) { cmp r3, #239 @ 0xef bls.n adds r3, #15 uxtb r3, r3 cmp r3, #2 b.n tapping_key.tap.interrupted = true; ldrb r3, [r5, #6] orr.w r3, r3, #1 strb r3, [r5, #6] if (TAP_GET_HOLD_ON_OTHER_KEY_PRESS b.n if (IS_TAPPING_RECORD(keyp) && !event.pressed) { cmp r0, r2 bne.n cbnz r7, process_record(keyp); mov r0, r4 keyp->tap = tapping_key.tap; strb r3, [r4, #6] process_record(keyp); bl tapping_key = *keyp; movs r2, #8 mov r1, r4 mov r0, r5 tapping_key = *keyp; bl b.n } else if (is_tap_record(keyp) && event.pressed) { mov r0, r4 bl cmp r0, #0 beq.n cmp r7, #0 beq.n if (tapping_key.tap.count > 1) { ldrb r3, [r5, #6] cmp r3, #31 bls.n process_record(&(keyrecord_t){ ldrh r2, [r5, #0] strh.w r2, [sp, #8] ldrb r2, [r5, #4] strb.w r2, [sp, #12] add r0, sp, #8 movs r2, #0 strh.w sl, [sp, #10] strb.w r2, [sp, #13] strb.w r3, [sp, #14] bl tapping_key = *keyp; movs r2, #8 mov r1, r4 ldr r0, [pc, #192] @ () bl b.n if (tapping_key.tap.count == 0) { ldrb r3, [r5, #6] cmp r3, #15 bhi.n debug_event(event); ldmia.w r9, {r0, r1} bl process_record(&tapping_key); mov r0, r5 bl tapping_key = (keyrecord_t){0}; movs r2, #8 movs r1, #0 mov r0, r5 bl debug_tapping_key(); bl return false; b.n if (IS_NOEVENT(event)) { cbz r2, if (IS_TAPPING_RECORD(keyp) && !event.pressed) { ldrh r1, [r5, #0] ldrh r2, [r4, #0] cmp r1, r2 bne.n cmp r7, #0 bne.n process_record(keyp); mov r0, r4 keyp->tap = tapping_key.tap; strb r3, [r4, #6] process_record(keyp); bl tapping_key = (keyrecord_t){0}; movs r2, #8 mov r1, r7 mov r0, r5 bl return true; movs r5, #1 b.n if (WITHIN_TAPPING_TERM(event) || MAYBE_RETRO_SHIFTING(event, keyp)) { cmp r3, #199 @ 0xc7 bhi.n if (IS_NOEVENT(event)) { cmp r2, #0 beq.n if (event.pressed) { cbz r7, if (IS_TAPPING_RECORD(keyp)) { ldrh r2, [r5, #0] ldrh r3, [r4, #0] cmp r2, r3 bne.n if (WITHIN_QUICK_TAP_TERM(event) && !tapping_key.tap.interrupted && tapping_key.tap.count > 0) { ldrb r3, [r5, #6] lsls r2, r3, #31 bmi.n cmp r3, #15 bls.n keyp->tap = tapping_key.tap; strb r3, [r4, #6] if (keyp->tap.count < 15) keyp->tap.count += 1; and.w r3, r3, #240 @ 0xf0 cmp r3, #240 @ 0xf0 beq.n ldrb r3, [r4, #6] ubfx r2, r3, #4, #4 adds r2, #1 bfi r3, r2, #4, #4 strb r3, [r4, #6] process_record(keyp); mov r0, r4 bl tapping_key = *keyp; ldr r0, [pc, #52] @ () movs r2, #8 mov r1, r4 b.n tapping_key = *keyp; movs r2, #8 mov r1, r4 ldr r0, [pc, #40] @ () bl return true; b.n } else if (is_tap_record(keyp)) { mov r0, r4 bl cmp r0, #0 bne.n tapping_key.tap.interrupted = true; ldrb r3, [r5, #6] orr.w r3, r3, #1 strb r3, [r5, #6] process_record(keyp); mov r0, r4 bl return true; b.n debug_event(event); ldmia.w r9, {r0, r1} bl tapping_key = (keyrecord_t){0}; b.n .word 0x20001088 : void action_tapping_process(keyrecord_t record) { push {r4, r5, r6, r7, lr} sub sp, #20 mov r4, sp stmia.w r4, {r0, r1} if (process_tapping(&record)) { mov r0, r4 bl ldr r7, [pc, #160] @ () ldr r5, [pc, #164] @ () mov r6, r0 cbz r0, if (IS_EVENT(record.event)) { ldrb.w r3, [sp, #4] cbz r3, debug_record(record); ldmia.w r4, {r0, r1} bl if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { ldr r4, [pc, #148] @ () for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { ldrb r0, [r5, #0] ldrb r3, [r7, #0] cmp r3, r0 bne.n } add sp, #20 pop {r4, r5, r6, r7, pc} if (!waiting_buffer_enq(record)) { ldmia.w r4, {r0, r1} add r3, sp, #8 stmia.w r3, {r0, r1} if (IS_NOEVENT(record.event)) { ldrb.w r1, [sp, #4] if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { ldrb r0, [r7, #0] ldrb r2, [r5, #0] if (IS_NOEVENT(record.event)) { cmp r1, #0 beq.n if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) { adds r4, r0, #1 and.w r4, r4, #7 cmp r4, r2 beq.n waiting_buffer[waiting_buffer_head] = record; mov r1, r3 ldr r3, [pc, #100] @ () movs r2, #8 add.w r0, r3, r0, lsl #3 bl waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE; strb r4, [r7, #0] debug_waiting_buffer(); bl return true; b.n clear_keyboard(); bl tapping_key = (keyrecord_t){0}; movs r2, #8 mov r1, r6 ldr r0, [pc, #76] @ () waiting_buffer_head = 0; strb r6, [r7, #0] waiting_buffer_tail = 0; strb r6, [r5, #0] tapping_key = (keyrecord_t){0}; bl b.n if (process_tapping(&waiting_buffer[waiting_buffer_tail])) { add.w r0, r4, r0, lsl #3 bl cmp r0, #0 beq.n debug_record(waiting_buffer[waiting_buffer_tail]); ldrb r3, [r5, #0] ldrh.w r0, [r4, r3, lsl #3] add.w r3, r4, r3, lsl #3 ldrh r6, [r3, #2] ldrh r2, [r3, #4] ldrh r1, [r3, #6] orr.w r0, r0, r6, lsl #16 orr.w r1, r2, r1, lsl #16 bl for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) { ldrb r3, [r5, #0] adds r3, #1 and.w r3, r3, #7 strb r3, [r5, #0] b.n nop .word 0x20001047 .word 0x20001046 .word 0x20001048 .word 0x20001088 : * S => oneshot state bits */ static uint8_t oneshot_layer_data = 0; inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; ldr r3, [pc, #4] @ () ldrb r0, [r3, #0] } lsrs r0, r0, #3 bx lr .word 0x200010b8 : inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; ldr r3, [pc, #8] @ () ldrb r0, [r3, #0] } and.w r0, r0, #7 bx lr nop .word 0x200010b8 : return oneshot_layer_data & 0b111; ldr r3, [pc, #12] @ () ldrb r0, [r3, #0] * * FIXME: needs doc */ bool is_oneshot_layer_active(void) { return get_oneshot_layer_state(); } ands.w r0, r0, #7 it ne movne r0, #1 bx lr nop .word 0x200010b8 : * * FIXME: needs doc */ uint8_t get_mods(void) { return real_mods; } ldr r3, [pc, #4] @ () ldrb r0, [r3, #0] bx lr nop .word 0x200010e4 : /** \brief add mods * * FIXME: needs doc */ void add_mods(uint8_t mods) { real_mods |= mods; ldr r3, [pc, #8] @ () ldrb r2, [r3, #0] orrs r0, r2 strb r0, [r3, #0] } bx lr nop .word 0x200010e4 : /** \brief del mods * * FIXME: needs doc */ void del_mods(uint8_t mods) { real_mods &= ~mods; ldr r2, [pc, #8] @ () ldrb r3, [r2, #0] bic.w r3, r3, r0 strb r3, [r2, #0] } bx lr .word 0x200010e4 : /** \brief clear mods * * FIXME: needs doc */ void clear_mods(void) { real_mods = 0; ldr r3, [pc, #4] @ () movs r2, #0 strb r2, [r3, #0] } bx lr .word 0x200010e4 : /** \brief add weak mods * * FIXME: needs doc */ void add_weak_mods(uint8_t mods) { weak_mods |= mods; ldr r3, [pc, #8] @ () ldrb r2, [r3, #0] orrs r0, r2 strb r0, [r3, #0] } bx lr nop .word 0x200010e3 : /** \brief del weak mods * * FIXME: needs doc */ void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; ldr r2, [pc, #8] @ () ldrb r3, [r2, #0] bic.w r3, r3, r0 strb r3, [r2, #0] } bx lr .word 0x200010e3 : /** \brief clear weak mods * * FIXME: needs doc */ void clear_weak_mods(void) { weak_mods = 0; ldr r3, [pc, #4] @ () movs r2, #0 strb r2, [r3, #0] } bx lr .word 0x200010e3 : /** \brief Called when the one shot modifiers have been changed. * * \param mods Contains the active modifiers active after the change. */ __attribute__((weak)) void oneshot_locked_mods_changed_user(uint8_t mods) {} bx lr : /** \brief Called when the locked one shot modifiers have been changed. * * \param mods Contains the active modifiers active after the change. */ __attribute__((weak)) void oneshot_locked_mods_changed_kb(uint8_t mods) { push {r3, lr} oneshot_locked_mods_changed_user(mods); bl } pop {r3, pc} ... : void del_oneshot_locked_mods(uint8_t mods) { push {r3, lr} if (oneshot_locked_mods & mods) { ldr r2, [pc, #20] @ () ldrb r3, [r2, #0] tst r3, r0 beq.n oneshot_locked_mods &= ~mods; bic.w r0, r3, r0 strb r0, [r2, #0] oneshot_locked_mods_changed_kb(oneshot_locked_mods); bl } pop {r3, pc} nop .word 0x200010b9 : /** \brief Called when the one shot modifiers have been changed. * * \param mods Contains the active modifiers active after the change. */ __attribute__((weak)) void oneshot_mods_changed_user(uint8_t mods) {} bx lr : /** \brief Called when the one shot modifiers have been changed. * * \param mods Contains the active modifiers active after the change. */ __attribute__((weak)) void oneshot_mods_changed_kb(uint8_t mods) { push {r3, lr} oneshot_mods_changed_user(mods); bl } pop {r3, pc} ... : void add_oneshot_mods(uint8_t mods) { push {r4, lr} if ((oneshot_mods & mods) != mods) { ldr r1, [pc, #20] @ () ldrb r3, [r1, #0] bics.w r4, r0, r3 beq.n oneshot_mods |= mods; orrs r3, r0 strb r3, [r1, #0] oneshot_mods_changed_kb(mods); bl } pop {r4, pc} nop .word 0x200010ba : void del_oneshot_mods(uint8_t mods) { push {r3, lr} if (oneshot_mods & mods) { ldr r2, [pc, #20] @ () ldrb r3, [r2, #0] tst r3, r0 beq.n oneshot_mods &= ~mods; bic.w r0, r3, r0 strb r0, [r2, #0] oneshot_mods_changed_kb(oneshot_mods); bl } pop {r3, pc} nop .word 0x200010ba : void clear_oneshot_mods(void) { push {r3, lr} if (oneshot_mods) { ldr r3, [pc, #16] @ () ldrb r2, [r3, #0] cbz r2, oneshot_mods = 0; movs r0, #0 strb r0, [r3, #0] oneshot_mods_changed_kb(oneshot_mods); bl } pop {r3, pc} nop .word 0x200010ba : static uint8_t get_mods_for_report(void) { push {r4, lr} uint8_t mods = real_mods | weak_mods; ldr r3, [pc, #32] @ () ldrb r4, [r3, #0] ldr r3, [pc, #32] @ () ldrb r3, [r3, #0] orrs r4, r3 if (oneshot_mods) { ldr r3, [pc, #28] @ () ldrb r3, [r3, #0] cbz r3, mods |= oneshot_mods; orrs r4, r3 if (has_anykey()) { bl cbz r0, clear_oneshot_mods(); bl } mov r0, r4 pop {r4, pc} nop .word 0x200010e4 .word 0x200010e3 .word 0x200010ba : void send_6kro_report(void) { push {r3, r4, r5, lr} keyboard_report->mods = get_mods_for_report(); ldr r4, [pc, #44] @ () ldr r5, [r4, #0] bl strb r0, [r5, #0] if (memcmp(keyboard_report, &last_report, sizeof(report_keyboard_t)) != 0) { ldr r4, [r4, #0] ldr r1, [pc, #36] @ () movs r2, #8 mov r0, r4 bl cbz r0, memcpy(&last_report, keyboard_report, sizeof(report_keyboard_t)); mov r1, r4 ldr r0, [pc, #20] @ () movs r2, #8 bl host_keyboard_send(keyboard_report); mov r0, r4 } ldmia.w sp!, {r3, r4, r5, lr} host_keyboard_send(keyboard_report); b.w } pop {r3, r4, r5, pc} .word 0x20000c04 .word 0x200010b0 : void send_nkro_report(void) { push {r3, r4, r5, lr} nkro_report->mods = get_mods_for_report(); ldr r4, [pc, #44] @ () ldr r5, [r4, #0] bl strb r0, [r5, #1] if (memcmp(nkro_report, &last_report, sizeof(report_nkro_t)) != 0) { ldr r4, [r4, #0] ldr r1, [pc, #36] @ () movs r2, #32 mov r0, r4 bl cbz r0, memcpy(&last_report, nkro_report, sizeof(report_nkro_t)); mov r1, r4 ldr r0, [pc, #20] @ () movs r2, #32 bl host_nkro_send(nkro_report); mov r0, r4 } ldmia.w sp!, {r3, r4, r5, lr} host_nkro_send(nkro_report); b.w } pop {r3, r4, r5, pc} .word 0x20000c00 .word 0x20001090 : if (keyboard_protocol && keymap_config.nkro) { ldr r3, [pc, #20] @ () ldrb r3, [r3, #0] cbz r3, ldr r3, [pc, #20] @ () ldrsb.w r3, [r3] cmp r3, #0 bge.n send_nkro_report(); b.w send_6kro_report(); b.w .word 0x20000c14 .word 0x20002048 : /** \brief Called when the one shot layers have been changed. * * \param layer Contains the layer that is toggled on, or zero when toggled off. */ __attribute__((weak)) void oneshot_layer_changed_user(uint8_t layer) {} bx lr : /** \brief Called when the one shot layers have been changed. * * \param layer Contains the layer that is toggled on, or zero when toggled off. */ __attribute__((weak)) void oneshot_layer_changed_kb(uint8_t layer) { push {r3, lr} oneshot_layer_changed_user(layer); bl } pop {r3, pc} ... : if (keymap_config.oneshot_enable) { ldr r2, [pc, #36] @ () ldrb r2, [r2, #1] lsls r2, r2, #29 void set_oneshot_layer(uint8_t layer, uint8_t state) { push {r4, lr} if (keymap_config.oneshot_enable) { bpl.n oneshot_layer_data = layer << 3 | state; ldr r4, [pc, #32] @ () orr.w r1, r1, r0, lsl #3 strb r1, [r4, #0] layer_on(layer); bl return oneshot_layer_data >> 3; ldrb r0, [r4, #0] oneshot_layer_changed_kb(get_oneshot_layer()); lsrs r0, r0, #3 bl } pop {r4, pc} ldmia.w sp!, {r4, lr} layer_on(layer); b.w .word 0x20002048 .word 0x200010b8 : void reset_oneshot_layer(void) { push {r3, lr} oneshot_layer_data = 0; ldr r3, [pc, #12] @ () movs r0, #0 strb r0, [r3, #0] oneshot_layer_changed_kb(get_oneshot_layer()); bl } pop {r3, pc} nop .word 0x200010b8 : void clear_oneshot_layer_state(oneshot_fullfillment_t state) { push {r3, lr} uint8_t start_state = oneshot_layer_data; ldr r2, [pc, #40] @ () ldrb r3, [r2, #0] oneshot_layer_data &= ~state; bic.w r0, r3, r0 strb r0, [r2, #0] if ((!get_oneshot_layer_state() && start_state != oneshot_layer_data) && keymap_config.oneshot_enable) { lsls r2, r0, #29 bne.n cmp r0, r3 beq.n ldr r3, [pc, #24] @ () ldrb r3, [r3, #1] lsls r3, r3, #29 bpl.n layer_off(get_oneshot_layer()); lsrs r0, r0, #3 bl } ldmia.w sp!, {r3, lr} reset_oneshot_layer(); b.w } pop {r3, pc} .word 0x200010b8 .word 0x20002048 : if (keymap_config.oneshot_enable != active) { ldr r2, [pc, #36] @ () void oneshot_set(bool active) { push {r3, lr} if (keymap_config.oneshot_enable != active) { ldrb r3, [r2, #1] ubfx r1, r3, #2, #1 cmp r1, r0 beq.n keymap_config.oneshot_enable = active; bfi r3, r0, #2, #1 strb r3, [r2, #1] eeconfig_update_keymap(keymap_config.raw); ldrh r0, [r2, #0] bl } ldmia.w sp!, {r3, lr} clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED); movs r0, #2 b.w } pop {r3, pc} nop .word 0x20002048 : oneshot_set(!keymap_config.oneshot_enable); ldr r3, [pc, #16] @ () ldrb r0, [r3, #1] ubfx r0, r0, #2, #1 eor.w r0, r0, #1 and.w r0, r0, #1 b.w .word 0x20002048 : oneshot_set(true); movs r0, #1 b.w : oneshot_set(false); movs r0, #0 b.w : /** \brief eeconfig disable * * FIXME: needs doc */ void eeconfig_disable(void) { push {r3, lr} #if defined(EEPROM_DRIVER) eeprom_driver_erase(); bl #endif eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); } ldmia.w sp!, {r3, lr} eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); movw r1, #65535 @ 0xffff movs r0, #0 b.w : /** \brief eeconfig is enabled * * FIXME: needs doc */ bool eeconfig_is_enabled(void) { push {r3, lr} bool is_eeprom_enabled = (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER); movs r0, #0 bl if (is_eeprom_enabled) { is_eeprom_enabled = via_eeprom_is_valid(); } #endif return is_eeprom_enabled; } movw r3, #65254 @ 0xfee6 subs r3, r0, r3 negs r0, r3 adcs r0, r3 pop {r3, pc} : /** \brief eeconfig read debug * * FIXME: needs doc */ uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); movs r0, #2 b.w : /** \brief eeconfig read default layer * * FIXME: needs doc */ uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); movs r0, #3 b.w : /** \brief eeconfig read keymap * * FIXME: needs doc */ uint16_t eeconfig_read_keymap(void) { return eeprom_read_word(EECONFIG_KEYMAP); movs r0, #4 b.w : } /** \brief eeconfig update keymap * * FIXME: needs doc */ void eeconfig_update_keymap(uint16_t val) { mov r1, r0 eeprom_update_word(EECONFIG_KEYMAP, val); movs r0, #4 b.w : } /** \brief eeconfig update kb * * FIXME: needs doc */ void eeconfig_update_kb(uint32_t val) { mov r1, r0 eeprom_update_dword(EECONFIG_KEYBOARD, val); movs r0, #15 b.w : } /** \brief eeconfig update user * * FIXME: needs doc */ void eeconfig_update_user(uint32_t val) { mov r1, r0 eeprom_update_dword(EECONFIG_USER, val); movs r0, #19 b.w : eeconfig_update_user(0); movs r0, #0 b.w : __attribute__((weak)) void eeconfig_init_kb(void) { push {r3, lr} eeconfig_update_kb(0); movs r0, #0 bl eeconfig_init_user(); bl } pop {r3, pc} ... : void eeconfig_init_quantum(void) { push {r0, r1, r2, lr} eeprom_driver_erase(); bl eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); movw r1, #65254 @ 0xfee6 movs r0, #0 bl eeprom_update_byte(EECONFIG_DEBUG, 0); movs r1, #0 movs r0, #2 bl default_layer_state = (layer_state_t)1 << 0; ldr r3, [pc, #112] @ () movs r1, #1 eeprom_update_byte(EECONFIG_DEFAULT_LAYER, default_layer_state); movs r0, #3 default_layer_state = (layer_state_t)1 << 0; strh r1, [r3, #0] eeprom_update_byte(EECONFIG_DEFAULT_LAYER, default_layer_state); bl eeprom_update_word(EECONFIG_KEYMAP, 0x1400); mov.w r1, #5120 @ 0x1400 movs r0, #4 bl eeprom_update_byte(EECONFIG_BACKLIGHT, 0); movs r1, #0 movs r0, #6 bl eeprom_update_byte(EECONFIG_AUDIO, 0); movs r1, #0 movs r0, #7 bl eeprom_update_dword(EECONFIG_RGBLIGHT, 0); movs r1, #0 movs r0, #8 bl eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, 0); movs r1, #0 movs r0, #36 @ 0x24 bl eeprom_update_byte(EECONFIG_UNUSED, 0); movs r1, #0 movs r0, #23 bl eeprom_update_byte(EECONFIG_UNICODEMODE, 0); movs r1, #0 movs r0, #12 bl eeprom_update_byte(EECONFIG_STENOMODE, 0); movs r1, #0 movs r0, #13 bl uint64_t dummy = 0; movs r3, #0 movs r2, #0 strd r2, r3, [sp] eeprom_update_block(&dummy, EECONFIG_RGB_MATRIX, sizeof(uint64_t)); mov r0, sp movs r2, #8 movs r1, #24 bl eeprom_update_dword(EECONFIG_HAPTIC, 0); movs r1, #0 movs r0, #32 bl eeconfig_init_kb(); bl } add sp, #12 ldr.w pc, [sp], #4 nop .word 0x20001044 : eeconfig_init_quantum(); b.w : } /** \brief eeconfig update split handedness * * FIXME: needs doc */ void eeconfig_update_handedness(bool val) { mov r1, r0 eeprom_update_byte(EECONFIG_HANDEDNESS, !!val); movs r0, #14 b.w : /** * @brief Generates a tick event at a maximum rate of 1KHz that drives the * internal QMK state machine. */ static inline void generate_tick_event(void) { push {r0, r1, r4, r5, r6, lr} static uint16_t last_tick = 0; const uint16_t now = timer_read(); if (TIMER_DIFF_16(now, last_tick) != 0) { ldr r5, [pc, #48] @ () const uint16_t now = timer_read(); bl if (TIMER_DIFF_16(now, last_tick) != 0) { ldrh r3, [r5, #0] cmp r3, r0 const uint16_t now = timer_read(); mov r4, r0 if (TIMER_DIFF_16(now, last_tick) != 0) { beq.n action_exec(MAKE_TICK_EVENT); movs r6, #0 strh.w r6, [sp] bl strh.w r6, [sp, #4] strh.w r0, [sp, #2] add r3, sp, #8 ldmdb r3, {r0, r1} bl last_tick = now; strh r4, [r5, #0] } } add sp, #8 pop {r4, r5, r6, pc} nop .word 0x200010e6 : void last_matrix_activity_trigger(void) { push {r3, lr} last_matrix_modification_time = last_input_modification_time = sync_timer_read32(); bl ldr r3, [pc, #8] @ () str r0, [r3, #0] ldr r3, [pc, #8] @ () str r0, [r3, #0] } pop {r3, pc} .word 0x200010fc .word 0x200010f8 : __attribute__((weak)) void matrix_setup(void) {} bx lr : __attribute__((weak)) void keyboard_pre_init_user(void) {} bx lr : __attribute__((weak)) void keyboard_pre_init_kb(void) { push {r3, lr} keyboard_pre_init_user(); bl } pop {r3, pc} : __attribute__((weak)) void keyboard_post_init_user(void) {} bx lr : __attribute__((weak)) void keyboard_post_init_kb(void) { push {r3, lr} keyboard_post_init_user(); bl } pop {r3, pc} : __attribute__((weak)) bool matrix_can_read(void) { movs r0, #1 bx lr ... : void keyboard_setup(void) { push {r3, lr} print_set_sendchar(sendchar); ldr r0, [pc, #20] @ () bl eeprom_driver_init(); bl matrix_setup(); bl keyboard_pre_init_kb(); bl } pop {r3, pc} nop .word 0x600036a9 : } movs r0, #1 bx lr : __attribute__((weak)) bool should_process_keypress(void) { push {r3, lr} return is_keyboard_master(); bl } pop {r3, pc} : __attribute__((weak)) void housekeeping_task_kb(void) {} bx lr : __attribute__((weak)) void housekeeping_task_user(void) {} bx lr : void housekeeping_task(void) { push {r3, lr} housekeeping_task_kb(); bl housekeeping_task_user(); bl } pop {r3, pc} : void quantum_init(void) { push {r3, lr} if (!eeconfig_is_enabled()) { bl cbnz r0, eeconfig_init(); bl debug_config.raw = eeconfig_read_debug(); bl ldr r3, [pc, #28] @ () strb r0, [r3, #0] keymap_config.raw = eeconfig_read_keymap(); bl ldr r3, [pc, #24] @ () strh r0, [r3, #0] layer_state_t default_layer = (layer_state_t)eeconfig_read_default_layer(); bl default_layer_set(default_layer); bl layer_state_set_kb((layer_state_t)layer_state); ldr r3, [pc, #16] @ () ldrh r0, [r3, #0] } ldmia.w sp!, {r3, lr} layer_state_set_kb((layer_state_t)layer_state); b.w .word 0x20001100 .word 0x20002048 .word 0x20001042 : void keyboard_init(void) { push {r3, lr} timer_init(); bl matrix_init(); bl quantum_init(); bl led_init_ports(); bl keyboard_post_init_kb(); /* Always keep this last */ bl } pop {r3, pc} : secure_task(); #endif } /** \brief Main task that is repeatedly called as fast as possible. */ void keyboard_task(void) { stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} sub sp, #20 if (!matrix_can_read()) { bl cbnz r0, generate_tick_event(); bl # endif #endif #ifdef MOUSEKEY_ENABLE // mousekey repeat & acceleration mousekey_task(); bl #ifdef HAPTIC_ENABLE haptic_task(); #endif led_task(); } add sp, #20 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} led_task(); b.w matrix_scan(); ldr r7, [pc, #180] @ () bl mov r6, r7 for (uint8_t row = 0; row < MATRIX_ROWS && !matrix_changed; row++) { movs r4, #0 matrix_changed |= matrix_previous[row] ^ matrix_get_row(row); mov r0, r4 for (uint8_t row = 0; row < MATRIX_ROWS && !matrix_changed; row++) { adds r4, #1 uxtb r4, r4 matrix_changed |= matrix_previous[row] ^ matrix_get_row(row); ldrb.w r5, [r6], #1 bl for (uint8_t row = 0; row < MATRIX_ROWS && !matrix_changed; row++) { cmp r4, #15 beq.n cmp r5, r0 beq.n if (debug_config.matrix) { ldr r3, [pc, #152] @ () ldrb r3, [r3, #0] lsls r3, r3, #30 bpl.n matrix_print(); bl const bool process_keypress = should_process_keypress(); bl mov.w r8, #0 str r0, [sp, #0] matrix_row_t col_mask = 1; mov.w sl, #1 uxtb.w r9, r8 const matrix_row_t current_row = matrix_get_row(row); mov r0, r9 bl const matrix_row_t row_changes = current_row ^ matrix_previous[row]; ldrb.w r3, [r7], #1 if (!row_changes || has_ghost_in_row(row, current_row)) { cmp r0, r3 const matrix_row_t current_row = matrix_get_row(row); mov r4, r0 if (!row_changes || has_ghost_in_row(row, current_row)) { beq.n const matrix_row_t row_changes = current_row ^ matrix_previous[row]; eors r3, r0 uxtb r3, r3 for (uint8_t col = 0; col < MATRIX_COLS; col++, col_mask <<= 1) { movs r5, #0 matrix_row_t col_mask = 1; movs r6, #1 action_exec(MAKE_KEYEVENT(row, col, key_pressed)); add.w fp, sp, #8 if (row_changes & col_mask) { tst r3, r6 beq.n if (process_keypress) { ldr r2, [sp, #0] cbz r2, str r3, [sp, #4] action_exec(MAKE_KEYEVENT(row, col, key_pressed)); strb.w r5, [sp, #8] strb.w r9, [sp, #9] bl const bool key_pressed = current_row & col_mask; tst r4, r6 ite ne movne r1, #1 moveq r1, #0 action_exec(MAKE_KEYEVENT(row, col, key_pressed)); strh.w r0, [sp, #10] strb.w sl, [sp, #12] const bool key_pressed = current_row & col_mask; strb.w r1, [sp, #13] action_exec(MAKE_KEYEVENT(row, col, key_pressed)); ldmia.w fp, {r0, r1} bl ldr r3, [sp, #4] for (uint8_t col = 0; col < MATRIX_COLS; col++, col_mask <<= 1) { adds r5, #1 uxtb r5, r5 lsls r6, r6, #1 cmp r5, #7 uxtb r6, r6 bne.n matrix_previous[row] = current_row; strb.w r4, [r7, #-1] for (uint8_t row = 0; row < MATRIX_ROWS; row++) { add.w r8, r8, #1 cmp.w r8, #15 bne.n last_matrix_activity_trigger(); bl activity_has_occurred = true; b.n if (!matrix_changed) { cmp r5, r0 bne.n b.n nop .word 0x200010e8 .word 0x20001100 : // 16bit keycodes - important uint16_t keycode = keymap_key_to_keycode(layer, key); return action_for_keycode(keycode); }; action_t action_for_keycode(uint16_t keycode) { push {r3, r4, r5, lr} // keycode remapping keycode = keycode_config(keycode); bl uint8_t action_layer, mod; (void)action_layer; (void)mod; switch (keycode) { cmp.w r0, #20992 @ 0x5200 keycode = keycode_config(keycode); mov r4, r0 switch (keycode) { bcs.n cmp.w r0, #20480 @ 0x5000 bcs.w cmp r0, #223 @ 0xdf bhi.n cmp r0, #204 @ 0xcc bhi.w cmp r0, #167 @ 0xa7 bhi.n cmp r0, #164 @ 0xa4 bhi.n cmp r0, #1 beq.n subs r3, r0, #4 uxth r3, r3 # endif // LEGACY_MAGIC_HANDLING break; #endif default: action.code = ACTION_NO; cmp r3, #161 @ 0xa1 it cs movcs r4, #0 break; } return action; } mov r0, r4 pop {r3, r4, r5, pc} switch (keycode) { sub.w r3, r0, #168 @ 0xa8 uxth r3, r3 cmp r3, #26 bls.n action.code = ACTION_NO; movs r4, #0 b.n switch (keycode) { cmp.w r0, #16384 @ 0x4000 bcs.n cmp.w r0, #8192 @ 0x2000 bcs.w cmp r0, #231 @ 0xe7 bls.n sub.w r3, r0, #256 @ 0x100 uxth r3, r3 cmp.w r3, #7936 @ 0x1f00 bcs.n action.code = ACTION_MODS_KEY(mod_config(QK_MODS_GET_MODS(keycode)), keycode_config(QK_MODS_GET_BASIC_KEYCODE(keycode))); // adds modifier to key ubfx r0, r0, #8, #8 bl mov r5, r0 uxtb r0, r4 bl lsls r5, r5, #8 and.w r5, r5, #7936 @ 0x1f00 orr.w r4, r0, r5 b.n action.code = ACTION_LAYER_TAP_KEY(QK_LAYER_TAP_GET_LAYER(keycode), keycode_config(QK_LAYER_TAP_GET_TAP_KEYCODE(keycode))); uxtb r0, r0 bl and.w r4, r4, #3840 @ 0xf00 orrs r0, r4 orr.w r0, r0, #40960 @ 0xa000 uxth r4, r0 break; b.n switch (keycode) { cmp.w r0, #21120 @ 0x5280 bcs.n movw r3, #21087 @ 0x525f cmp r0, r3 bhi.n movw r3, #21055 @ 0x523f cmp r0, r3 bhi.n movw r3, #21023 @ 0x521f cmp r0, r3 bhi.n action.code = ACTION_LAYER_GOTO(action_layer); and.w r4, r0, #3 movs r3, #1 ubfx r2, r0, #2, #6 lsls r3, r4 orr.w r3, r3, r2, lsl #5 orr.w r3, r3, #36096 @ 0x8d00 action.code = ACTION_DEFAULT_LAYER_SET(action_layer); uxth r4, r3 break; b.n action.code = ACTION_DEFAULT_LAYER_SET(action_layer); and.w r4, r0, #3 movs r3, #1 ubfx r2, r0, #2, #3 lsls r3, r4 orr.w r3, r3, r2, lsl #5 orr.w r3, r3, #35840 @ 0x8c00 b.n switch (keycode) { movw r3, #21183 @ 0x52bf cmp r0, r3 bhi.n movw r3, #21151 @ 0x529f cmp r0, r3 and.w r0, r0, #31 bhi.n action.code = ACTION_LAYER_ONESHOT(action_layer); movw r3, #41204 @ 0xa0f4 orr.w r4, r3, r0, lsl #8 break; b.n switch (keycode) { sub.w r3, r0, #21120 @ 0x5280 subs r3, #64 @ 0x40 uxth r3, r3 cmp r3, #31 bhi.n action.code = ACTION_LAYER_TAP_TOGGLE(QK_LAYER_TAP_TOGGLE_GET_LAYER(keycode)); lsls r4, r0, #8 and.w r4, r4, #7936 @ 0x1f00 orr.w r4, r4, #40960 @ 0xa000 orr.w r4, r4, #240 @ 0xf0 break; b.n action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode)); sub.w r4, r0, #36 @ 0x24 orr.w r4, r4, #16384 @ 0x4000 action.code = ACTION_MOUSEKEY(keycode); uxth r4, r4 break; b.n action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode)); adds r4, #88 @ 0x58 ldr r3, [pc, #132] @ () uxtb r4, r4 ldrh.w r4, [r3, r4, lsl #1] orr.w r4, r4, #17408 @ 0x4400 break; b.n action.code = ACTION_MOUSEKEY(keycode); orr.w r4, r0, #20480 @ 0x5000 b.n action.code = ACTION_LAYER_MOMENTARY(action_layer); and.w r4, r0, #31 movw r3, #41201 @ 0xa0f1 orr.w r4, r3, r4, lsl #8 break; b.n action.code = ACTION_LAYER_TOGGLE(action_layer); and.w r4, r0, #3 movs r3, #1 ubfx r2, r0, #2, #3 lsls r3, r4 orr.w r3, r3, r2, lsl #5 orr.w r3, r3, #35328 @ 0x8a00 b.n mod = mod_config(QK_ONE_SHOT_MOD_GET_MODS(keycode)); bl action.code = ACTION_MODS_ONESHOT(mod); lsls r4, r0, #8 and.w r4, r4, #7936 @ 0x1f00 orr.w r4, r4, #8192 @ 0x2000 break; b.n mod = mod_config(QK_LAYER_MOD_GET_MODS(keycode)); and.w r0, r0, #31 bl action.code = ACTION_LAYER_MODS(action_layer, (mod & 0x10) ? mod << 4 : mod); lsls r3, r0, #27 ubfx r4, r4, #5, #4 it mi lslmi r0, r0, #4 lsls r4, r4, #8 sxth r0, r0 orrs r4, r0 orr.w r4, r4, #36864 @ 0x9000 b.n mod = mod_config(QK_MOD_TAP_GET_MODS(keycode)); ubfx r0, r0, #8, #5 bl mov r5, r0 action.code = ACTION_MODS_TAP_KEY(mod, keycode_config(QK_MOD_TAP_GET_TAP_KEYCODE(keycode))); uxtb r0, r4 bl lsls r5, r5, #8 and.w r5, r5, #7936 @ 0x1f00 orrs r5, r0 orr.w r5, r5, #8192 @ 0x2000 uxth r4, r5 break; b.n .word 0x60008b1c : // translates key to keycode __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) { sub sp, #8 strh.w r1, [sp, #4] ubfx r1, r1, #8, #8 if (key.row < MATRIX_ROWS && key.col < MATRIX_COLS) { cmp r1, #14 bhi.n ldrb.w r2, [sp, #4] cmp r2, #6 bhi.n return keycode_at_dip_switch_map_location(key.col, false); } #endif // DIP_SWITCH_MAP_ENABLE return KC_NO; } add sp, #8 return keycode_at_keymap_location(layer, key.row, key.col); b.w } movs r0, #0 add sp, #8 bx lr : action_t action_for_key(uint8_t layer, keypos_t key) { push {r0, r1, r2, lr} strh.w r1, [sp, #4] uint16_t keycode = keymap_key_to_keycode(layer, key); ldr r1, [sp, #4] bl }; add sp, #12 ldr.w lr, [sp], #4 return action_for_keycode(keycode); b.w : * * This function is used to check a specific keycode against the bootmagic config, * and will return the corrected keycode, when appropriate. */ __attribute__((weak)) uint16_t keycode_config(uint16_t keycode) { switch (keycode) { cmp r0, #231 @ 0xe7 bhi.n cmp r0, #223 @ 0xdf bhi.n cmp r0, #49 @ 0x31 beq.n bhi.n cmp r0, #41 @ 0x29 beq.n cmp r0, #42 @ 0x2a beq.n bx lr sub.w r3, r0, #224 @ 0xe0 cmp r3, #7 bhi.n tbb [pc, r3] .word 0x28234015 .word 0x413c4031 cmp r0, #57 @ 0x39 beq.n cmp r0, #130 @ 0x82 beq.n cmp r0, #53 @ 0x35 beq.n bx lr case KC_CAPS_LOCK: case KC_LOCKING_CAPS_LOCK: if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) { ldr r3, [pc, #200] @ () ldrb r2, [r3, #0] lsls r2, r2, #30 bne.n return KC_LEFT_CTRL; } else if (keymap_config.swap_escape_capslock) { ldrb r3, [r3, #1] return KC_ESCAPE; tst.w r3, #8 it ne movne r0, #41 @ 0x29 bx lr } return keycode; case KC_LEFT_CTRL: if (keymap_config.swap_control_capslock) { ldr r2, [pc, #180] @ () ldrb r3, [r2, #0] lsls r1, r3, #31 bmi.n return KC_CAPS_LOCK; } if (keymap_config.swap_lctl_lgui) { ldrb r2, [r2, #1] tst.w r2, #1 } return KC_LEFT_GUI; } return KC_LEFT_CTRL; case KC_LEFT_ALT: if (keymap_config.swap_lalt_lgui) { beq.n return KC_LEFT_GUI; tst.w r3, #16 ite ne movne r0, #0 moveq r0, #227 @ 0xe3 bx lr if (keymap_config.swap_lalt_lgui) { ldr r3, [pc, #152] @ () ldrb r3, [r3, #0] tst.w r3, #4 b.n } return KC_LEFT_GUI; } return KC_LEFT_ALT; case KC_LEFT_GUI: if (keymap_config.swap_lalt_lgui) { ldr r2, [pc, #140] @ () ldrb r3, [r2, #0] lsls r1, r3, #29 bmi.n return KC_LEFT_ALT; } if (keymap_config.swap_lctl_lgui) { ldrb r2, [r2, #1] lsls r2, r2, #31 bpl.n return KC_LEFT_CTRL; movs r0, #224 @ 0xe0 bx lr if (keymap_config.no_gui) { return KC_NO; } return KC_LEFT_GUI; case KC_RIGHT_CTRL: if (keymap_config.swap_rctl_rgui) { ldr r3, [pc, #124] @ () ldrb r2, [r3, #1] lsls r1, r2, #30 bpl.n if (keymap_config.no_gui) { ldrb r3, [r3, #0] return KC_NO; } return KC_RIGHT_GUI; tst.w r3, #16 ite ne movne r0, #0 moveq r0, #231 @ 0xe7 bx lr } return KC_RIGHT_CTRL; case KC_RIGHT_ALT: if (keymap_config.swap_ralt_rgui) { ldr r3, [pc, #100] @ () ldrb r3, [r3, #0] lsls r2, r3, #28 bmi.n } return KC_BACKSPACE; default: return keycode; } } bx lr if (keymap_config.swap_ralt_rgui) { ldr r2, [pc, #92] @ () ldrb r3, [r2, #0] lsls r1, r3, #28 bmi.n if (keymap_config.swap_rctl_rgui) { ldrb r2, [r2, #1] lsls r1, r2, #30 bpl.n return KC_RIGHT_CTRL; movs r0, #228 @ 0xe4 bx lr if (keymap_config.swap_grave_esc) { ldr r3, [pc, #72] @ () ldrb r3, [r3, #0] return KC_ESCAPE; tst.w r3, #32 b.n if (keymap_config.swap_grave_esc) { ldr r3, [pc, #64] @ () ldrb r2, [r3, #0] lsls r2, r2, #26 bmi.n } else if (keymap_config.swap_escape_capslock) { ldrb r3, [r3, #1] return KC_CAPS_LOCK; tst.w r3, #8 it ne movne r0, #57 @ 0x39 bx lr if (keymap_config.swap_backslash_backspace) { ldr r3, [pc, #44] @ () ldrb r3, [r3, #0] return KC_BACKSPACE; tst.w r3, #64 @ 0x40 it ne movne r0, #42 @ 0x2a bx lr if (keymap_config.swap_backslash_backspace) { ldr r3, [pc, #28] @ () ldrb r3, [r3, #0] return KC_BACKSLASH; tst.w r3, #64 @ 0x40 it ne movne r0, #49 @ 0x31 bx lr return KC_CAPS_LOCK; movs r0, #57 @ 0x39 bx lr return KC_LEFT_ALT; movs r0, #226 @ 0xe2 bx lr return KC_RIGHT_ALT; movs r0, #230 @ 0xe6 bx lr return KC_GRAVE; movs r0, #53 @ 0x35 b.n nop .word 0x20002048 : * * This function checks the mods passed to it against the bootmagic config, * and will remove or replace mods, based on that. */ __attribute__((weak)) uint8_t mod_config(uint8_t mod) { push {r4, lr} /** * Note: This function is for the 5-bit packed mods, NOT the full 8-bit mods. * More info about the mods can be seen in modifiers.h. */ if (keymap_config.swap_lalt_lgui) { ldr r4, [pc, #188] @ () ldrb r1, [r4, #0] lsls r3, r1, #29 bpl.n /** If both modifiers pressed or neither pressed, do nothing * Otherwise swap the values * Note: The left mods are ANDed with the right-hand values to check * if they were pressed with the right hand bit set */ if (((mod & MOD_RALT) == MOD_LALT) ^ ((mod & MOD_RGUI) == MOD_LGUI)) { and.w r2, r0, #20 sub.w ip, r2, #4 and.w r3, r0, #24 rsbs r2, ip, #0 adc.w r2, r2, ip sub.w ip, r3, #8 rsbs r3, ip, #0 adc.w r3, r3, ip cmp r2, r3 mod ^= (MOD_LALT | MOD_LGUI); it ne eorne.w r0, r0, #12 } } if (keymap_config.swap_ralt_rgui) { lsls r3, r1, #28 bpl.n if (((mod & MOD_RALT) == MOD_RALT) ^ ((mod & MOD_RGUI) == MOD_RGUI)) { and.w r2, r0, #20 sub.w ip, r2, #20 and.w r3, r0, #24 rsbs r2, ip, #0 adc.w r2, r2, ip sub.w ip, r3, #24 rsbs r3, ip, #0 adc.w r3, r3, ip cmp r2, r3 /* lefthand values to preserve the right hand bit */ mod ^= (MOD_LALT | MOD_LGUI); it ne eorne.w r0, r0, #12 } } if (keymap_config.swap_lctl_lgui) { ldrb r4, [r4, #1] lsls r3, r4, #31 bpl.n /* left mods ANDed with right-hand values to check for right hand bit */ if (((mod & MOD_RCTL) == MOD_LCTL) ^ ((mod & MOD_RGUI) == MOD_LGUI)) { and.w r2, r0, #17 add.w ip, r2, #4294967295 @ 0xffffffff and.w r3, r0, #24 rsbs r2, ip, #0 adc.w r2, r2, ip sub.w ip, r3, #8 rsbs r3, ip, #0 adc.w r3, r3, ip cmp r2, r3 mod ^= (MOD_LCTL | MOD_LGUI); it ne eorne.w r0, r0, #9 } } if (keymap_config.swap_rctl_rgui) { lsls r3, r4, #30 bpl.n if (((mod & MOD_RCTL) == MOD_RCTL) ^ ((mod & MOD_RGUI) == MOD_RGUI)) { and.w r2, r0, #17 and.w r3, r0, #24 sub.w r4, r2, #17 negs r2, r4 sub.w ip, r3, #24 adcs r2, r4 rsbs r3, ip, #0 adc.w r3, r3, ip cmp r2, r3 /* lefthand values to preserve the right hand bit */ mod ^= (MOD_LCTL | MOD_LGUI); it ne eorne.w r0, r0, #9 } } if (keymap_config.no_gui) { lsls r3, r1, #27 mod &= ~MOD_LGUI; mod &= ~MOD_RGUI; it mi andmi.w r0, r0, #231 @ 0xe7 } return mod; } pop {r4, pc} nop .word 0x20002048 : #include "sendchar.h" /* default noop "null" implementation */ __attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; } movs r0, #0 bx lr : // bind lib/printf to console interface - sendchar static int8_t null_sendchar_func(uint8_t c) { return 0; } movs r0, #0 bx lr : static sendchar_func_t func = null_sendchar_func; void print_set_sendchar(sendchar_func_t send) { func = send; ldr r3, [pc, #4] @ () str r0, [r3, #0] } bx lr nop .word 0x20000c08 : __attribute__((weak)) void matrix_scan_kb(void) { matrix_scan_user(); } __attribute__((weak)) void matrix_init_user(void) {} bx lr : __attribute__((weak)) void matrix_scan_user(void) {} bx lr : __attribute__((weak)) void matrix_scan_kb(void) { push {r3, lr} matrix_scan_user(); bl } pop {r3, pc} : #ifdef MATRIX_MASKED return matrix[row] & matrix_mask[row]; #else return matrix[row]; #endif } ldr r3, [pc, #4] @ () ldrb r0, [r3, r0] bx lr nop .word 0x20002059 : print_hex8(row); print(": "); print_matrix_row(row); print("\n"); } } bx lr : __attribute__((weak)) void matrix_io_delay(void) { wait_us(MATRIX_IO_DELAY); } __attribute__((weak)) void matrix_output_select_delay(void) { waitInputPinDelay(); } bx lr : setPinOutput(pin); writePinHigh(pin); } } static inline void setPinInputHigh_atomic(pin_t pin) { push {r3, lr} \details Assigns the given value to the Base Priority register. \param [in] basePri Base Priority value to set */ __STATIC_FORCEINLINE void __set_BASEPRI(uint32_t basePri) { __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); movs r3, #48 @ 0x30 msr BASEPRI, r3 ATOMIC_BLOCK_FORCEON { setPinInputHigh(pin); movs r2, #3 uxtb r1, r0 bfc r0, #0, #12 bl <_pal_lld_setpadmode> movs r3, #0 msr BASEPRI, r3 } } pop {r3, pc} : for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { unselect_row(x); } } __attribute__((weak)) void matrix_init_pins(void) { push {r3, r4, r5, lr} ldr r5, [pc, #48] @ () movs r4, #15 pin_t pin = row_pins[row]; ldr.w r0, [r5], #4 if (pin != NO_PIN) { adds r2, r0, #1 beq.n setPinInputHigh_atomic(pin); bl for (uint8_t x = 0; x < ROWS_PER_HAND; x++) { subs r4, #1 ands.w r4, r4, #255 @ 0xff bne.n ldr r5, [pc, #28] @ () movs r4, #7 unselect_rows(); for (uint8_t x = 0; x < MATRIX_COLS; x++) { if (col_pins[x] != NO_PIN) { ldr.w r0, [r5], #4 adds r3, r0, #1 beq.n setPinInputHigh_atomic(col_pins[x]); bl for (uint8_t x = 0; x < MATRIX_COLS; x++) { subs r4, #1 ands.w r4, r4, #255 @ 0xff bne.n } } } pop {r3, r4, r5, pc} .word 0x60008b70 .word 0x60008b54 : __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} pin_t pin = row_pins[row]; ldr.w r8, [pc, #148] @ ldr.w r4, [r8, r1, lsl #2] __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { mov r5, r1 if (pin != NO_PIN) { adds r1, r4, #1 __attribute__((weak)) void matrix_read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row) { mov r7, r0 if (pin != NO_PIN) { beq.n movs r3, #48 @ 0x30 msr BASEPRI, r3 setPinOutput(pin); ldr.w r9, [pc, #132] @ and.w r6, r4, r9 uxtb r4, r4 mov r1, r4 mov r0, r6 movs r2, #6 bl <_pal_lld_setpadmode> writePinLow(pin); mov r1, r4 movs r2, #0 mov r0, r6 bl <_pal_lld_writepad> movs r4, #0 msr BASEPRI, r4 matrix_row_t current_row_value = 0; if (!select_row(current_row)) { // Select row return; // skip NO_PIN row } matrix_output_select_delay(); bl // For each col... matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { ldr.w fp, [pc, #96] @ matrix_output_select_delay(); movs r6, #7 matrix_row_t row_shifter = MATRIX_ROW_SHIFTER; mov.w sl, #1 uint8_t pin_state = readMatrixPin(col_pins[col_index]); ldr.w r0, [fp], #4 if (pin != NO_PIN) { adds r2, r0, #1 bne.n matrix_row_t current_row_value = 0; movs r3, #0 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { subs r6, #1 // Populate the matrix row with the state of the col pin current_row_value |= pin_state ? 0 : row_shifter; orrs r3, r4 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { mov.w sl, sl, lsl #1 ands.w r6, r6, #255 @ 0xff current_row_value |= pin_state ? 0 : row_shifter; uxtb r4, r3 for (uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++, row_shifter <<= 1) { uxtb.w sl, sl bne.n pin_t pin = row_pins[row]; ldr.w r0, [r8, r5, lsl #2] if (pin != NO_PIN) { adds r3, r0, #1 beq.n setPinInputHigh_atomic(pin); bl } // Unselect row unselect_row(current_row); matrix_output_unselect_delay(current_row, current_row_value != 0); // wait for all Col signals to go HIGH subs r1, r4, #0 it ne movne r1, #1 mov r0, r5 bl // Update the matrix current_matrix[current_row] = current_row_value; strb r4, [r7, r5] } ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} return (readPin(pin) == MATRIX_INPUT_PRESSED_STATE) ? 0 : 1; uxtb r1, r0 and.w r0, r0, r9 bl <_pal_lld_readpad> current_row_value |= pin_state ? 0 : row_shifter; cmp r0, #0 bne.n mov r3, sl b.n nop .word 0x60008b70 .word 0xfffff000 .word 0x60008b54 : # endif // defined(MATRIX_ROW_PINS) && defined(MATRIX_COL_PINS) #else # error DIODE_DIRECTION is not defined! #endif void matrix_init(void) { push {r4, lr} // initialize key pins matrix_init_pins(); // initialize matrix state: all keys off memset(matrix, 0, sizeof(matrix)); movs r4, #15 matrix_init_pins(); bl memset(matrix, 0, sizeof(matrix)); mov r2, r4 movs r1, #0 ldr r0, [pc, #28] @ () bl memset(raw_matrix, 0, sizeof(raw_matrix)); mov r2, r4 movs r1, #0 ldr r0, [pc, #24] @ () bl debounce_init(ROWS_PER_HAND); mov r0, r4 bl matrix_init_kb(); } ldmia.w sp!, {r4, lr} matrix_init_kb(); b.w nop .word 0x20002059 .word 0x2000204a : transport_master(master_matrix, slave_matrix); return true; // Treat the transport as always connected } #endif uint8_t matrix_scan(void) { push {r4, r5, lr} sub sp, #20 matrix_row_t curr_matrix[MATRIX_ROWS] = {0}; movs r2, #15 movs r1, #0 mov r0, sp bl movs r4, #0 #if defined(DIRECT_PINS) || (DIODE_DIRECTION == COL2ROW) // Set row, read cols for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { matrix_read_cols_on_row(curr_matrix, current_row); uxtb r1, r4 mov r0, sp for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { adds r4, #1 matrix_read_cols_on_row(curr_matrix, current_row); bl for (uint8_t current_row = 0; current_row < ROWS_PER_HAND; current_row++) { cmp r4, #15 bne.n for (uint8_t current_col = 0; current_col < MATRIX_COLS; current_col++, row_shifter <<= 1) { matrix_read_rows_on_col(curr_matrix, current_col, row_shifter); } #endif bool changed = memcmp(raw_matrix, curr_matrix, sizeof(curr_matrix)) != 0; ldr r0, [pc, #52] @ () mov r2, r4 mov r1, sp bl cmp r0, #0 ite ne movne r5, #1 moveq r5, #0 if (changed) memcpy(raw_matrix, curr_matrix, sizeof(curr_matrix)); beq.n ldr r0, [pc, #32] @ () mov r2, r4 mov r1, sp bl #ifdef SPLIT_KEYBOARD changed = debounce(raw_matrix, matrix + thisHand, ROWS_PER_HAND, changed) | matrix_post_scan(); #else changed = debounce(raw_matrix, matrix, ROWS_PER_HAND, changed); ldr r1, [pc, #24] @ () ldr r0, [pc, #20] @ () mov r3, r5 movs r2, #15 bl mov r4, r0 matrix_scan_kb(); bl #endif return (uint8_t)changed; } mov r0, r4 add sp, #20 pop {r4, r5, pc} .word 0x2000204a .word 0x20002059 : static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time); static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows); // we use num_rows rather than MATRIX_ROWS to support split keyboards void debounce_init(uint8_t num_rows) { push {r4, lr} debounce_counters = (debounce_counter_t *)malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t)); rsb r4, r0, r0, lsl #3 mov r0, r4 bl ldr r3, [pc, #12] @ () int i = 0; for (uint8_t r = 0; r < num_rows; r++) { for (uint8_t c = 0; c < MATRIX_COLS; c++) { debounce_counters[i++] = DEBOUNCE_ELAPSED; mov r2, r4 movs r1, #0 } } } ldmia.w sp!, {r4, lr} debounce_counters = (debounce_counter_t *)malloc(num_rows * MATRIX_COLS * sizeof(debounce_counter_t)); str r0, [r3, #0] debounce_counters[i++] = DEBOUNCE_ELAPSED; b.w .word 0x20001108 : void debounce_free(void) { free(debounce_counters); debounce_counters = NULL; } bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} bool updated_last = false; cooked_changed = false; if (counters_need_update) { ldr r4, [pc, #292] @ () cooked_changed = false; ldr r5, [pc, #296] @ () if (counters_need_update) { ldrb r7, [r4, #0] ldr.w r8, [pc, #296] @ bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { sub sp, #20 mov r6, r3 cooked_changed = false; movs r3, #0 bool debounce(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows, bool changed) { str r0, [sp, #8] str r1, [sp, #12] str r2, [sp, #4] cooked_changed = false; strb r3, [r5, #0] if (counters_need_update) { cmp r7, #0 beq.w #else # define TIMER_DIFF_FAST(a, b) TIMER_DIFF_32(a, b) # define timer_expired_fast(current, future) timer_expired32(current, future) typedef uint32_t fast_timer_t; fast_timer_t inline timer_read_fast(void) { return timer_read32(); bl fast_timer_t now = timer_read_fast(); fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); ldr r3, [pc, #272] @ () ldr r1, [r3, #0] last_time = now; str r0, [r3, #0] fast_timer_t elapsed_time = TIMER_DIFF_FAST(now, last_time); subs r1, r0, r1 updated_last = true; if (elapsed_time > UINT8_MAX) { cmp r1, #255 @ 0xff bhi.n elapsed_time = UINT8_MAX; } if (elapsed_time > 0) { cbz r1, // If the current time is > debounce counter, set the counter to enable input. static void update_debounce_counters(uint8_t num_rows, uint8_t elapsed_time) { counters_need_update = false; matrix_need_update = false; debounce_counter_t *debounce_pointer = debounce_counters; ldr r3, [pc, #260] @ () counters_need_update = false; movs r2, #0 debounce_counter_t *debounce_pointer = debounce_counters; ldr.w ip, [r3] counters_need_update = false; strb r2, [r4, #0] update_debounce_counters(num_rows, elapsed_time); uxtb r1, r1 matrix_need_update = false; strb.w r2, [r8] for (uint8_t row = 0; row < num_rows; row++) { mov r9, r2 mov lr, r2 for (uint8_t col = 0; col < MATRIX_COLS; col++) { if (*debounce_pointer != DEBOUNCE_ELAPSED) { if (*debounce_pointer <= elapsed_time) { *debounce_pointer = DEBOUNCE_ELAPSED; mov fp, r2 for (uint8_t row = 0; row < num_rows; row++) { ldr r0, [sp, #4] uxtb r3, r2 cmp r0, r3 bhi.n cmp.w r9, #0 beq.n movs r3, #1 strb.w r3, [r8] cmp.w lr, #0 beq.n movs r3, #1 strb r3, [r4, #0] if (changed || matrix_need_update) { cbnz r6, for (uint8_t row = 0; row < num_rows; row++) { mov r6, r7 if (changed || matrix_need_update) { ldrb.w r3, [r8] cbz r3, if (!updated_last) { cbnz r6, bl last_time = timer_read_fast(); ldr r3, [pc, #188] @ () str r0, [r3, #0] } // upload from raw_matrix to final matrix; static void transfer_matrix_values(matrix_row_t raw[], matrix_row_t cooked[], uint8_t num_rows) { matrix_need_update = false; debounce_counter_t *debounce_pointer = debounce_counters; ldr r2, [pc, #188] @ () matrix_need_update = false; movs r3, #0 strb.w r3, [r8] debounce_counter_t *debounce_pointer = debounce_counters; ldr.w r8, [r2] for (uint8_t row = 0; row < num_rows; row++) { ldr r2, [sp, #12] mov ip, r3 subs r6, r2, #1 matrix_row_t delta = raw[row] ^ cooked[row]; matrix_row_t existing_row = cooked[row]; for (uint8_t col = 0; col < MATRIX_COLS; col++) { matrix_row_t col_mask = (ROW_SHIFTER << col); mov.w r9, #1 if (delta & col_mask) { if (*debounce_pointer == DEBOUNCE_ELAPSED) { *debounce_pointer = DEBOUNCE; mov.w sl, #20 for (uint8_t row = 0; row < num_rows; row++) { ldr r0, [sp, #4] uxtb r2, r3 rsb r1, r3, r3, lsl #3 cmp r0, r2 add r1, r8 bhi.n cmp.w ip, #0 beq.n movs r3, #1 strb r3, [r5, #0] strb r3, [r4, #0] return cooked_changed; ldrb r0, [r5, #0] } add sp, #20 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} elapsed_time = UINT8_MAX; movs r1, #255 @ 0xff b.n add.w r3, ip, #4294967295 @ 0xffffffff for (uint8_t col = 0; col < MATRIX_COLS; col++) { add.w sl, ip, #6 if (*debounce_pointer != DEBOUNCE_ELAPSED) { ldrb.w r0, [r3, #1]! cbz r0, if (*debounce_pointer <= elapsed_time) { cmp r1, r0 *debounce_pointer -= elapsed_time; iteet cc subcc r0, r0, r1 *debounce_pointer = DEBOUNCE_ELAPSED; strbcs.w fp, [r3] matrix_need_update = true; movcs r9, r7 *debounce_pointer -= elapsed_time; strbcc r0, [r3, #0] it cc movcc lr, r7 for (uint8_t col = 0; col < MATRIX_COLS; col++) { cmp r3, sl bne.n add.w ip, ip, #7 for (uint8_t row = 0; row < num_rows; row++) { adds r2, #1 b.n matrix_row_t delta = raw[row] ^ cooked[row]; ldr r2, [sp, #8] ldrb r0, [r6, #1] ldrb r7, [r2, r3] movs r2, #0 eors r7, r0 matrix_row_t col_mask = (ROW_SHIFTER << col); lsl.w lr, r9, r2 if (delta & col_mask) { tst.w lr, r7 matrix_row_t col_mask = (ROW_SHIFTER << col); uxtb.w fp, lr if (delta & col_mask) { beq.n if (*debounce_pointer == DEBOUNCE_ELAPSED) { ldrb.w lr, [r1, r2] cmp.w lr, #0 bne.n *debounce_pointer = DEBOUNCE; strb.w sl, [r1, r2] counters_need_update = true; existing_row ^= col_mask; // flip the bit. eor.w r0, fp, r0 mov.w ip, #1 for (uint8_t col = 0; col < MATRIX_COLS; col++) { adds r2, #1 cmp r2, #7 bne.n cooked_changed = true; } } debounce_pointer++; } cooked[row] = existing_row; strb.w r0, [r6, #1]! for (uint8_t row = 0; row < num_rows; row++) { adds r3, #1 b.n if (changed || matrix_need_update) { cmp r6, #0 beq.n b.n nop .word 0x20001103 .word 0x20001101 .word 0x20001102 .word 0x20001104 .word 0x20001108 : void protocol_pre_task(void); void protocol_post_task(void); // Bodge as refactoring this area sucks.... void protocol_init(void) __attribute__((weak)); void protocol_init(void) { push {r3, lr} protocol_pre_init(); bl keyboard_init(); bl protocol_post_init(); } ldmia.w sp!, {r3, lr} protocol_post_init(); b.w : void protocol_task(void) __attribute__((weak)); void protocol_task(void) { push {r3, lr} protocol_pre_task(); bl keyboard_task(); bl protocol_post_task(); } ldmia.w sp!, {r3, lr} protocol_post_task(); b.w
: /** \brief Main * * FIXME: Needs doc */ int main(void) __attribute__((weak)); int main(void) { push {r3, lr} platform_setup(); bl protocol_setup(); bl keyboard_setup(); bl protocol_init(); bl /* Main loop */ while (true) { protocol_task(); bl // Run deferred executions void deferred_exec_task(void); deferred_exec_task(); #endif // DEFERRED_EXEC_ENABLE housekeeping_task(); bl while (true) { b.n : #include #include #include "eeprom_driver.h" uint8_t eeprom_read_byte(const uint8_t *addr) { push {r0, r1, r2, lr} uint8_t ret = 0; movs r3, #0 uint8_t eeprom_read_byte(const uint8_t *addr) { mov r1, r0 eeprom_read_block(&ret, addr, 1); movs r2, #1 add.w r0, sp, #7 uint8_t ret = 0; strb.w r3, [sp, #7] eeprom_read_block(&ret, addr, 1); bl return ret; } ldrb.w r0, [sp, #7] add sp, #12 ldr.w pc, [sp], #4 : uint16_t eeprom_read_word(const uint16_t *addr) { push {r0, r1, r2, lr} uint16_t ret = 0; movs r3, #0 uint16_t eeprom_read_word(const uint16_t *addr) { mov r1, r0 eeprom_read_block(&ret, addr, 2); movs r2, #2 add.w r0, sp, #6 uint16_t ret = 0; strh.w r3, [sp, #6] eeprom_read_block(&ret, addr, 2); bl return ret; } ldrh.w r0, [sp, #6] add sp, #12 ldr.w pc, [sp], #4 : uint32_t eeprom_read_dword(const uint32_t *addr) { push {r0, r1, r2, lr} uint32_t ret = 0; eeprom_read_block(&ret, addr, 4); movs r2, #4 uint32_t eeprom_read_dword(const uint32_t *addr) { mov r1, r0 uint32_t ret = 0; movs r3, #0 eeprom_read_block(&ret, addr, 4); add.w r0, sp, r2 uint32_t ret = 0; str r3, [sp, #4] eeprom_read_block(&ret, addr, 4); bl return ret; } ldr r0, [sp, #4] add sp, #12 ldr.w pc, [sp], #4 : void eeprom_write_byte(uint8_t *addr, uint8_t value) { push {r0, r1, r2, lr} eeprom_write_block(&value, addr, 1); movs r2, #1 void eeprom_write_byte(uint8_t *addr, uint8_t value) { strb.w r1, [sp, #7] eeprom_write_block(&value, addr, 1); mov r1, r0 add.w r0, sp, #7 bl } add sp, #12 ldr.w pc, [sp], #4 : void eeprom_write_word(uint16_t *addr, uint16_t value) { push {r0, r1, r2, lr} eeprom_write_block(&value, addr, 2); movs r2, #2 void eeprom_write_word(uint16_t *addr, uint16_t value) { strh.w r1, [sp, #6] eeprom_write_block(&value, addr, 2); mov r1, r0 add.w r0, sp, #6 bl } add sp, #12 ldr.w pc, [sp], #4 : void eeprom_write_dword(uint32_t *addr, uint32_t value) { push {r0, r1, r2, lr} eeprom_write_block(&value, addr, 4); movs r2, #4 void eeprom_write_dword(uint32_t *addr, uint32_t value) { str r1, [sp, #4] eeprom_write_block(&value, addr, 4); mov r1, r0 add.w r0, sp, r2 bl } add sp, #12 ldr.w pc, [sp], #4 : void eeprom_update_block(const void *buf, void *addr, size_t len) { push {r3, r4, r5, r6, r7, lr} uint8_t read_buf[len]; adds r3, r2, #7 bic.w r3, r3, #7 void eeprom_update_block(const void *buf, void *addr, size_t len) { add r7, sp, #0 uint8_t read_buf[len]; sub.w sp, sp, r3 void eeprom_update_block(const void *buf, void *addr, size_t len) { mov r5, r0 mov r4, r2 eeprom_read_block(read_buf, addr, len); mov r0, sp void eeprom_update_block(const void *buf, void *addr, size_t len) { mov r6, r1 eeprom_read_block(read_buf, addr, len); bl if (memcmp(buf, read_buf, len) != 0) { mov r2, r4 mov r1, sp mov r0, r5 bl cbz r0, eeprom_write_block(buf, addr, len); mov r2, r4 mov r1, r6 mov r0, r5 bl } } mov sp, r7 pop {r3, r4, r5, r6, r7, pc} : void eeprom_update_byte(uint8_t *addr, uint8_t value) { push {r3, r4, r5, lr} mov r4, r1 mov r5, r0 uint8_t orig = eeprom_read_byte(addr); bl if (orig != value) { cmp r0, r4 beq.n eeprom_write_byte(addr, value); mov r1, r4 mov r0, r5 } } ldmia.w sp!, {r3, r4, r5, lr} eeprom_write_byte(addr, value); b.w } pop {r3, r4, r5, pc} : void eeprom_update_word(uint16_t *addr, uint16_t value) { push {r3, r4, r5, lr} mov r4, r1 mov r5, r0 uint16_t orig = eeprom_read_word(addr); bl if (orig != value) { cmp r0, r4 beq.n eeprom_write_word(addr, value); mov r1, r4 mov r0, r5 } } ldmia.w sp!, {r3, r4, r5, lr} eeprom_write_word(addr, value); b.w } pop {r3, r4, r5, pc} : void eeprom_update_dword(uint32_t *addr, uint32_t value) { push {r3, r4, r5, lr} mov r4, r1 mov r5, r0 uint32_t orig = eeprom_read_dword(addr); bl if (orig != value) { cmp r0, r4 beq.n eeprom_write_dword(addr, value); mov r1, r4 mov r0, r5 } } ldmia.w sp!, {r3, r4, r5, lr} eeprom_write_dword(addr, value); b.w } pop {r3, r4, r5, pc} : void eeprom_driver_init(void) { eeprom_driver_erase(); } void eeprom_driver_erase(void) { memset(transientBuffer, 0x00, TRANSIENT_EEPROM_SIZE); ldr r0, [pc, #8] @ () movs r2, #40 @ 0x28 movs r1, #0 b.w nop .word 0x2000110c : eeprom_driver_erase(); b.w : } void eeprom_read_block(void *buf, const void *addr, size_t len) { push {r4, r5, r6, lr} mov r5, r1 mov r4, r2 intptr_t offset = (intptr_t)addr; memset(buf, 0x00, len); movs r1, #0 void eeprom_read_block(void *buf, const void *addr, size_t len) { mov r6, r0 memset(buf, 0x00, len); bl if (offset + len > TRANSIENT_EEPROM_SIZE) { adds r3, r5, r4 cmp r3, #40 @ 0x28 len = TRANSIENT_EEPROM_SIZE - offset; it hi rsbhi r4, r5, #40 @ 0x28 len = clamp_length(offset, len); if (len > 0) { cbz r4, memcpy(buf, &transientBuffer[offset], len); ldr r1, [pc, #16] @ () mov r2, r4 add r1, r5 mov r0, r6 } } ldmia.w sp!, {r4, r5, r6, lr} memcpy(buf, &transientBuffer[offset], len); b.w } pop {r4, r5, r6, pc} .word 0x2000110c : void eeprom_write_block(const void *buf, void *addr, size_t len) { mov r3, r1 if (offset + len > TRANSIENT_EEPROM_SIZE) { add r1, r2 cmp r1, #40 @ 0x28 len = TRANSIENT_EEPROM_SIZE - offset; it hi rsbhi r2, r3, #40 @ 0x28 intptr_t offset = (intptr_t)addr; len = clamp_length(offset, len); if (len > 0) { cbz r2, memcpy(&transientBuffer[offset], buf, len); mov r1, r0 ldr r0, [pc, #8] @ () add r0, r3 b.w } } bx lr nop .word 0x2000110c : * Used to ensure that the correct keycode is released if the key is released. */ static bool grave_esc_was_shifted = false; bool process_grave_esc(uint16_t keycode, keyrecord_t *record) { if (keycode == QK_GRAVE_ESCAPE) { movw r3, #31766 @ 0x7c16 cmp r0, r3 bool process_grave_esc(uint16_t keycode, keyrecord_t *record) { push {r4, lr} mov r4, r1 if (keycode == QK_GRAVE_ESCAPE) { bne.n const uint8_t mods = get_mods(); bl if (mods & MOD_MASK_SHIFT) { shifted = 0; } #endif if (record->event.pressed) { ldrb r2, [r4, #5] ldr r3, [pc, #52] @ () cbz r2, uint8_t shifted = mods & MOD_MASK_SG; and.w r0, r0, #170 @ 0xaa grave_esc_was_shifted = shifted; cmp r0, #0 iteet ne movne r2, #1 moveq r2, #0 add_key_to_report(key); moveq r0, #41 @ 0x29 movne r0, #53 @ 0x35 strb r2, [r3, #0] bl add_key(shifted ? KC_GRAVE : KC_ESCAPE); } else { del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE); } send_keyboard_report(); bl return false; movs r0, #0 } // Not a grave keycode so continue processing return true; } pop {r4, pc} del_key(grave_esc_was_shifted ? KC_GRAVE : KC_ESCAPE); ldrb r3, [r3, #0] cmp r3, #0 del_key_from_report(key); ite eq moveq r0, #41 @ 0x29 movne r0, #53 @ 0x35 bl } b.n return true; movs r0, #1 b.n .word 0x20001134 : #endif /** * MAGIC actions (BOOTMAGIC without the boot) */ bool process_magic(uint16_t keycode, keyrecord_t *record) { push {r3, r4, r5, lr} mov r5, r0 // skip anything that isn't a keyup if (record->event.pressed) { ldrb r0, [r1, #5] cmp r0, #0 beq.w if (IS_MAGIC_KEYCODE(keycode)) { sub.w r5, r5, #28672 @ 0x7000 uxth r3, r5 cmp r3, #34 @ 0x22 bhi.w /* keymap config */ keymap_config.raw = eeconfig_read_keymap(); bl ldr r4, [pc, #424] @ () switch (keycode) { subs r5, #1 keymap_config.raw = eeconfig_read_keymap(); strh r0, [r4, #0] switch (keycode) { cmp r5, #33 @ 0x21 bhi.n tbb [pc, r5] .short 0xbd4d .word 0x591f1b55 .word 0x2f695d23 .word 0x376d33b5 .word 0x753b9771 .word 0x837b419f .word 0x652b6127 .word 0xa98e7f47 .word 0xc55116b3 case QK_MAGIC_SWAP_CONTROL_CAPS_LOCK: keymap_config.swap_control_capslock = true; ldrb r3, [r4, #0] orr.w r3, r3, #1 break; case QK_MAGIC_TOGGLE_GUI: keymap_config.no_gui = !keymap_config.no_gui; break; case QK_MAGIC_TOGGLE_CONTROL_CAPS_LOCK: keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; strb r3, [r4, #0] break; b.n keymap_config.swap_escape_capslock = true; ldrb r3, [r4, #1] orr.w r3, r3, #8 case QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK: keymap_config.swap_escape_capslock = !keymap_config.swap_escape_capslock; strb r3, [r4, #1] break; b.n keymap_config.capslock_to_control = true; ldrb r3, [r4, #0] orr.w r3, r3, #2 b.n keymap_config.swap_lalt_lgui = true; ldrb r3, [r4, #0] orr.w r3, r3, #4 b.n keymap_config.swap_ralt_rgui = true; ldrb r3, [r4, #0] orr.w r3, r3, #8 b.n keymap_config.swap_lctl_lgui = true; ldrb r3, [r4, #1] orr.w r3, r3, #1 b.n keymap_config.swap_rctl_rgui = true; ldrb r3, [r4, #1] orr.w r3, r3, #2 b.n keymap_config.no_gui = true; ldrb r3, [r4, #0] orr.w r3, r3, #16 b.n keymap_config.swap_grave_esc = true; ldrb r3, [r4, #0] orr.w r3, r3, #32 b.n keymap_config.swap_backslash_backspace = true; ldrb r3, [r4, #0] orr.w r3, r3, #64 @ 0x40 b.n clear_keyboard(); // clear first buffer to prevent stuck keys bl keymap_config.nkro = true; ldrb r3, [r4, #0] orr.w r3, r3, #128 @ 0x80 b.n keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = true; ldrb r3, [r4, #0] bic.w r3, r3, #12 orr.w r3, r3, #12 b.n keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = true; ldrb r3, [r4, #1] bic.w r3, r3, #3 orr.w r3, r3, #3 b.n keymap_config.swap_control_capslock = false; ldrb r3, [r4, #0] bic.w r3, r3, #1 b.n keymap_config.swap_escape_capslock = false; ldrb r3, [r4, #1] bic.w r3, r3, #8 b.n keymap_config.capslock_to_control = false; ldrb r3, [r4, #0] bic.w r3, r3, #2 b.n keymap_config.swap_lalt_lgui = false; ldrb r3, [r4, #0] bic.w r3, r3, #4 b.n keymap_config.swap_ralt_rgui = false; ldrb r3, [r4, #0] bic.w r3, r3, #8 b.n keymap_config.swap_lctl_lgui = false; ldrb r3, [r4, #1] bic.w r3, r3, #1 b.n keymap_config.swap_rctl_rgui = false; ldrb r3, [r4, #1] bic.w r3, r3, #2 b.n keymap_config.no_gui = false; ldrb r3, [r4, #0] bic.w r3, r3, #16 b.n keymap_config.swap_grave_esc = false; ldrb r3, [r4, #0] bic.w r3, r3, #32 b.n keymap_config.swap_backslash_backspace = false; ldrb r3, [r4, #0] bic.w r3, r3, #64 @ 0x40 b.n clear_keyboard(); // clear first buffer to prevent stuck keys bl keymap_config.nkro = false; ldrb r3, [r4, #0] bic.w r3, r3, #128 @ 0x80 b.n keymap_config.swap_lalt_lgui = keymap_config.swap_ralt_rgui = false; ldrb r3, [r4, #0] bic.w r3, r3, #12 b.n keymap_config.swap_lctl_lgui = keymap_config.swap_rctl_rgui = false; ldrb r3, [r4, #1] bic.w r3, r3, #3 b.n keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui; ldrb r3, [r4, #0] ubfx r2, r3, #2, #1 eor.w r2, r2, #1 uxtb r2, r2 bfi r3, r2, #2, #1 keymap_config.swap_ralt_rgui = keymap_config.swap_lalt_lgui; bfi r3, r2, #3, #1 b.n keymap_config.swap_lctl_lgui = !keymap_config.swap_lctl_lgui; ldrb r3, [r4, #1] mvns r2, r3 and.w r2, r2, #1 bfi r3, r2, #0, #1 keymap_config.swap_rctl_rgui = keymap_config.swap_lctl_lgui; bfi r3, r2, #1, #1 b.n keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace; ldrb r3, [r4, #0] ubfx r2, r3, #6, #1 eor.w r2, r2, #1 bfi r3, r2, #6, #1 b.n clear_keyboard(); // clear first buffer to prevent stuck keys bl keymap_config.nkro = !keymap_config.nkro; ldrb r3, [r4, #0] ubfx r2, r3, #7, #1 eor.w r2, r2, #1 bfi r3, r2, #7, #1 b.n eeconfig_update_handedness(true); movs r0, #1 eeconfig_update_handedness(false); bl } eeconfig_update_keymap(keymap_config.raw); ldrh r0, [r4, #0] bl clear_keyboard(); // clear to prevent stuck keys bl return false; movs r0, #0 } } // Not a magic keycode so continue processing return true; } pop {r3, r4, r5, pc} eeconfig_update_handedness(false); movs r0, #0 b.n keymap_config.no_gui = !keymap_config.no_gui; ldrb r3, [r4, #0] ubfx r2, r3, #4, #1 eor.w r2, r2, #1 bfi r3, r2, #4, #1 b.n keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock; ldrb r3, [r4, #0] ubfx r2, r3, #0, #1 eor.w r2, r2, #1 bfi r3, r2, #0, #1 b.n keymap_config.swap_escape_capslock = !keymap_config.swap_escape_capslock; ldrb r3, [r4, #1] ubfx r2, r3, #3, #1 eor.w r2, r2, #1 bfi r3, r2, #3, #1 b.n return true; movs r0, #1 b.n .word 0x20002048 : #include "mousekey.h" static inline int8_t times_inv_sqrt2(int8_t x) { // 181/256 (0.70703125) is used as an approximation for 1/sqrt(2) // because it is close to the exact value which is 0.707106781 const int16_t n = x * 181; add.w r3, r0, r0, lsl #1 rsb r3, r3, r3, lsl #4 add.w r0, r0, r3, lsl #2 uxth r3, r0 sxth r0, r0 // To ensure that the integer result is rounded accurately after // division, check the sign of the numerator: // If negative, subtract half of the denominator before dividing // Otherwise, add half of the denominator before dividing return n < 0 ? (n - d / 2) / d : (n + d / 2) / d; cmp r0, #0 bge.n subs r0, #128 @ 0x80 sxth r0, r0 cmp r0, #0 bge.n adds r0, #255 @ 0xff sbfx r0, r0, #8, #8 } bx lr return n < 0 ? (n - d / 2) / d : (n + d / 2) / d; add.w r0, r3, #128 @ 0x80 b.n ... : /* Default accelerated mode */ static uint8_t move_unit(void) { uint16_t unit; if (mousekey_accel & (1 << 0)) { ldr r3, [pc, #88] @ () ldrb r3, [r3, #0] lsls r1, r3, #31 bpl.n unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; ldr r3, [pc, #84] @ () ldrb r0, [r3, #0] lsls r0, r0, #1 } else if (mousekey_repeat >= mk_time_to_max) { unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; } else { unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; } return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); cmp r0, #127 @ 0x7f bhi.n cbz r0, uxtb r0, r0 bx lr } else if (mousekey_accel & (1 << 1)) { lsls r2, r3, #30 bpl.n unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 2; ldr r3, [pc, #64] @ () ldrb r0, [r3, #0] lsls r0, r0, #2 b.n } else if (mousekey_accel & (1 << 2)) { lsls r3, r3, #29 bpl.n unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed); ldr r3, [pc, #52] @ () ldrb r0, [r3, #0] unit = MOUSEKEY_MOVE_DELTA * mk_max_speed; lsls r0, r0, #3 b.n } else if (mousekey_repeat == 0) { ldr r3, [pc, #48] @ () ldrb r3, [r3, #0] cbz r3, } else if (mousekey_repeat >= mk_time_to_max) { ldr r2, [pc, #48] @ () unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; ldr r1, [pc, #36] @ () } else if (mousekey_repeat >= mk_time_to_max) { ldrb r2, [r2, #0] unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed) / 4; ldrb r0, [r1, #0] } else if (mousekey_repeat >= mk_time_to_max) { cmp r3, r2 bcs.n unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max; smulbb r0, r0, r3 lsls r0, r0, #3 udiv r0, r0, r2 uxth r0, r0 b.n unit = MOUSEKEY_MOVE_DELTA; movs r0, #8 b.n return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit)); movs r0, #127 @ 0x7f bx lr movs r0, #1 } bx lr .word 0x2000113c .word 0x20000c11 .word 0x2000113b .word 0x20000c10 : # endif // end MOUSEKEY_INERTIA mode static uint8_t wheel_unit(void) { uint16_t unit; if (mousekey_accel & (1 << 0)) { ldr r3, [pc, #80] @ () ldrb r3, [r3, #0] lsls r1, r3, #31 bpl.n unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; ldr r3, [pc, #76] @ () ldrb r0, [r3, #0] lsrs r0, r0, #2 } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed; } else { unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max; } return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); cbz r0, uxtb r0, r0 bx lr } else if (mousekey_accel & (1 << 1)) { lsls r2, r3, #30 bpl.n unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 2; ldr r3, [pc, #60] @ () ldrb r0, [r3, #0] lsrs r0, r0, #1 return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); b.n } else if (mousekey_accel & (1 << 2)) { lsls r3, r3, #29 bpl.n unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed); ldr r3, [pc, #48] @ () ldrb r0, [r3, #0] return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); cmp r0, #127 @ 0x7f bls.n movs r0, #127 @ 0x7f bx lr } else if (mousekey_wheel_repeat == 0) { ldr r3, [pc, #40] @ () ldrb r3, [r3, #0] cbz r3, } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { ldr r2, [pc, #40] @ () unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; ldr r1, [pc, #28] @ () } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { ldrb r2, [r2, #0] unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed) / 4; ldrb r0, [r1, #0] } else if (mousekey_wheel_repeat >= mk_wheel_time_to_max) { cmp r3, r2 unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_wheel_repeat) / mk_wheel_time_to_max; itt cc smulbbcc r0, r0, r3 udivcc r0, r0, r2 b.n unit = MOUSEKEY_WHEEL_DELTA; movs r0, #1 b.n return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit)); movs r0, #1 } bx lr .word 0x2000113c .word 0x20000c0d .word 0x2000113a .word 0x20000c0c : } // save the state for later memcpy(&mouse_report, &tmpmr, sizeof(tmpmr)); } void mousekey_on(uint8_t code) { push {r4, lr} # endif # ifndef MOUSEKEY_INERTIA // If mouse report is not zero, the current mousekey press is overlapping // with another. Restart acceleration for smoother directional transition. if (mouse_report.x || mouse_report.y || mouse_report.h || mouse_report.v) { ldr r4, [pc, #172] @ () ldrb r2, [r4, #3] ldrb r3, [r4, #2] orrs r3, r2 ldrb r2, [r4, #5] orrs r3, r2 ldrb r2, [r4, #4] orrs r3, r2 beq.n # ifdef MK_KINETIC_SPEED mouse_timer = timer_read() - (MOUSEKEY_INTERVAL << 2); # else mousekey_repeat = MOUSEKEY_MOVE_DELTA; ldr r3, [pc, #156] @ () movs r2, #8 strb r2, [r3, #0] mousekey_wheel_repeat = MOUSEKEY_WHEEL_DELTA; ldr r3, [pc, #156] @ () movs r2, #1 strb r2, [r3, #0] if (mousekey_frame < 2) mouse_report.x = move_unit(0); } # else // no inertia if (code == KC_MS_UP) sub.w r3, r0, #205 @ 0xcd cmp r3, #18 bhi.n tbb [pc, r3] .word 0x17120f0a .word 0x2a2a2a2a .word 0x2a2a2a2a .word 0x27221e1a .short 0x3731 .byte 0x3c .byte 0x00 mouse_report.y = move_unit() * -1; bl negs r0, r0 else if (code == KC_MS_DOWN) mouse_report.y = move_unit(); strb r0, [r4, #3] mousekey_accel |= (1 << 0); else if (code == KC_MS_ACCEL1) mousekey_accel |= (1 << 1); else if (code == KC_MS_ACCEL2) mousekey_accel |= (1 << 2); } pop {r4, pc} mouse_report.y = move_unit(); bl b.n mouse_report.x = move_unit() * -1; bl negs r0, r0 mouse_report.x = move_unit(); strb r0, [r4, #2] b.n bl b.n mouse_report.v = wheel_unit(); bl mouse_report.v = wheel_unit() * -1; strb r0, [r4, #4] b.n bl negs r0, r0 b.n mouse_report.h = wheel_unit() * -1; bl negs r0, r0 mouse_report.h = wheel_unit(); strb r0, [r4, #5] b.n bl b.n mouse_report.buttons |= 1 << (code - KC_MS_BTN1); ldrb r2, [r4, #1] subs r0, #209 @ 0xd1 movs r3, #1 lsls r3, r0 orrs r3, r2 strb r3, [r4, #1] b.n mousekey_accel |= (1 << 0); ldr r2, [pc, #44] @ () ldrb r3, [r2, #0] orr.w r3, r3, #1 mousekey_accel |= (1 << 2); strb r3, [r2, #0] } b.n mousekey_accel |= (1 << 1); ldr r2, [pc, #32] @ () ldrb r3, [r2, #0] orr.w r3, r3, #2 b.n mousekey_accel |= (1 << 2); ldr r2, [pc, #20] @ () ldrb r3, [r2, #0] orr.w r3, r3, #4 b.n nop .word 0x2000113d .word 0x2000113b .word 0x2000113a .word 0x2000113c : void mousekey_off(uint8_t code) { push {r4, r5, lr} else if ((code == KC_MS_RIGHT) && (mousekey_x_dir > -1)) mousekey_x_dir = 0; # else // no inertia if (code == KC_MS_UP && mouse_report.y < 0) ldr r3, [pc, #260] @ () cmp r0, #205 @ 0xcd ldrsb.w r5, [r3, #3] mouse_report.y = 0; else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0; else if (code == KC_MS_LEFT && mouse_report.x < 0) ldrsb.w r4, [r3, #2] else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0; # endif // inertia or not else if (code == KC_MS_WH_UP && mouse_report.v > 0) ldrsb.w r1, [r3, #4] mouse_report.v = 0; else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0; else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) ldrsb.w r2, [r3, #5] if (code == KC_MS_UP && mouse_report.y < 0) bne.n cmp r5, #0 bge.n mouse_report.y = 0; movs r2, #0 strb r2, [r3, #3] mousekey_accel &= ~(1 << 0); else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1 << 1); else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1 << 2); if (mouse_report.x == 0 && mouse_report.y == 0) { ldrb r1, [r3, #3] ldrb r2, [r3, #2] orrs r2, r1 sxtb r1, r2 cbnz r2, mousekey_repeat = 0; ldr r2, [pc, #224] @ () strb r1, [r2, #0] # ifdef MK_KINETIC_SPEED mouse_timer = 0; # endif /* #ifdef MK_KINETIC_SPEED */ } if (mouse_report.v == 0 && mouse_report.h == 0) mousekey_wheel_repeat = 0; ldrb r2, [r3, #4] ldrb r3, [r3, #5] orrs r3, r2 sxtb r2, r3 cbnz r3, ldr r3, [pc, #212] @ () strb r2, [r3, #0] } pop {r4, r5, pc} else if (code == KC_MS_DOWN && mouse_report.y > 0) cmp r0, #206 @ 0xce bne.n cmp r5, #0 bgt.n b.n else if (code == KC_MS_LEFT && mouse_report.x < 0) cmp r0, #207 @ 0xcf bne.n cmp r4, #0 bge.n mouse_report.x = 0; movs r2, #0 strb r2, [r3, #2] b.n else if (code == KC_MS_RIGHT && mouse_report.x > 0) cmp r0, #208 @ 0xd0 bne.n cmp r4, #0 bgt.n b.n else if (code == KC_MS_WH_UP && mouse_report.v > 0) cmp r0, #217 @ 0xd9 bne.n cmp r1, #0 ble.n mouse_report.v = 0; movs r2, #0 strb r2, [r3, #4] b.n else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) cmp r0, #218 @ 0xda bne.n cmp r1, #0 bge.n b.n else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) cmp r0, #219 @ 0xdb bne.n cmp r2, #0 bge.n mouse_report.h = 0; movs r2, #0 strb r2, [r3, #5] b.n else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) cmp r0, #220 @ 0xdc bne.n cmp r2, #0 bgt.n b.n else if (IS_MOUSEKEY_BUTTON(code)) subs r0, #209 @ 0xd1 cmp r0, #14 bhi.n add r2, pc, #4 @ (adr r2, ) ldr.w pc, [r2, r0, lsl #2] .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x6000403d .word 0x60003f85 .word 0x60003f85 .word 0x60003f85 .word 0x60003f85 .word 0x6000404b .word 0x60004057 .word 0x60004061 mouse_report.buttons &= ~(1 << (code - KC_MS_BTN1)); ldrb r2, [r3, #1] movs r1, #1 lsls r1, r0 bic.w r2, r2, r1 strb r2, [r3, #1] b.n mousekey_accel &= ~(1 << 0); ldr r1, [pc, #44] @ () ldrb r2, [r1, #0] bic.w r2, r2, #1 mousekey_accel &= ~(1 << 2); strb r2, [r1, #0] b.n mousekey_accel &= ~(1 << 1); ldr r1, [pc, #32] @ () ldrb r2, [r1, #0] bic.w r2, r2, #2 b.n mousekey_accel &= ~(1 << 2); ldr r1, [pc, #20] @ () ldrb r2, [r1, #0] bic.w r2, r2, #4 b.n nop .word 0x2000113d .word 0x2000113b .word 0x2000113a .word 0x2000113c : # endif } #endif /* #ifndef MK_3_SPEED */ void mousekey_send(void) { push {r3, lr} mousekey_debug(); uint16_t time = timer_read(); bl if (mouse_report.x || mouse_report.y) last_timer_c = time; ldr r3, [pc, #36] @ () ldrb r2, [r3, #2] ldrb r1, [r3, #3] orrs r2, r1 itt ne ldrne r2, [pc, #28] @ () strhne r0, [r2, #0] if (mouse_report.v || mouse_report.h) last_timer_w = time; ldrb r2, [r3, #4] ldrb r3, [r3, #5] orrs r2, r3 itt ne ldrne r3, [pc, #20] @ () strhne r0, [r3, #0] host_mouse_send(&mouse_report); } ldmia.w sp!, {r3, lr} host_mouse_send(&mouse_report); ldr r0, [pc, #4] @ () b.w nop .word 0x2000113d .word 0x20001138 .word 0x20001136 : void mousekey_clear(void) { push {r3, lr} mouse_report = (report_mouse_t){}; movs r2, #6 ldr r0, [pc, #20] @ () movs r1, #0 bl mousekey_repeat = 0; ldr r2, [pc, #16] @ () movs r3, #0 strb r3, [r2, #0] mousekey_wheel_repeat = 0; ldr r2, [pc, #16] @ () strb r3, [r2, #0] mousekey_accel = 0; ldr r2, [pc, #16] @ () strb r3, [r2, #0] mousekey_x_inertia = 0; mousekey_y_inertia = 0; mousekey_x_dir = 0; mousekey_y_dir = 0; #endif } pop {r3, pc} .word 0x2000113d .word 0x2000113b .word 0x2000113a .word 0x2000113c : report_mouse_t mousekey_get_report(void) { return mouse_report; } bool should_mousekey_report_send(report_mouse_t *mouse_report) { return mouse_report->x || mouse_report->y || mouse_report->v || mouse_report->h; ldrsb.w r3, [r0, #2] cbnz r3, ldrsb.w r3, [r0, #3] cbnz r3, ldrsb.w r3, [r0, #4] cbnz r3, ldrsb.w r0, [r0, #5] subs r0, #0 it ne movne r0, #1 bx lr movs r0, #1 } bx lr ... : void mousekey_task(void) { push {r0, r1, r2, r4, r5, lr} report_mouse_t tmpmr = mouse_report; ldr r4, [pc, #356] @ () movs r2, #6 mov r1, r4 mov r0, sp bl mouse_report.x = 0; movs r3, #0 if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { ldrb.w r2, [sp, #3] mouse_report.x = 0; strb r3, [r4, #2] mouse_report.y = 0; strb r3, [r4, #3] mouse_report.v = 0; strb r3, [r4, #4] mouse_report.h = 0; strb r3, [r4, #5] if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { ldrb.w r3, [sp, #2] orrs r3, r2 beq.n ldr r3, [pc, #324] @ () ldrh r0, [r3, #0] bl ldr r1, [pc, #320] @ () ldrb r3, [r1, #0] cbz r3, ldr r2, [pc, #320] @ () ldrb r2, [r2, #0] cmp r0, r2 bgt.n if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) { ldrb.w r3, [sp, #4] ldrb.w r2, [sp, #5] orrs r3, r2 beq.n ldr r3, [pc, #304] @ () ldrh r0, [r3, #0] bl ldr r1, [pc, #300] @ () ldrb r3, [r1, #0] cmp r3, #0 beq.n ldr r2, [pc, #296] @ () ldrb r2, [r2, #0] cmp r0, r2 bgt.n if (has_mouse_report_changed(&mouse_report, &tmpmr) || should_mousekey_report_send(&mouse_report)) { ldr r0, [pc, #264] @ () mov r1, sp bl cbnz r0, ldr r0, [pc, #252] @ () bl cbz r0, mousekey_send(); bl memcpy(&mouse_report, &tmpmr, sizeof(tmpmr)); movs r2, #6 mov r1, sp ldr r0, [pc, #236] @ () bl } add sp, #12 pop {r4, r5, pc} if ((tmpmr.x || tmpmr.y) && timer_elapsed(last_timer_c) > (mousekey_repeat ? mk_interval : mk_delay * 10)) { ldr r2, [pc, #256] @ () ldrb r2, [r2, #0] add.w r2, r2, r2, lsl #2 cmp.w r0, r2, lsl #1 ble.n if (mousekey_repeat != UINT8_MAX) mousekey_repeat++; adds r3, #1 strb r3, [r1, #0] b.n cmp r3, #255 @ 0xff bne.n if (tmpmr.x != 0) mouse_report.x = move_unit() * ((tmpmr.x > 0) ? 1 : -1); ldrsb.w r5, [sp, #2] cbz r5, bl cmp r5, #0 ite le movle r3, #255 @ 0xff movgt r3, #1 muls r3, r0 strb r3, [r4, #2] if (tmpmr.y != 0) mouse_report.y = move_unit() * ((tmpmr.y > 0) ? 1 : -1); ldrsb.w r5, [sp, #3] cbz r5, bl cmp r5, #0 ite le movle r3, #255 @ 0xff movgt r3, #1 muls r3, r0 strb r3, [r4, #3] if (mouse_report.x && mouse_report.y) { ldrsb.w r0, [r4, #2] cmp r0, #0 beq.n ldrsb.w r2, [r4, #3] cmp r2, #0 beq.n mouse_report.x = times_inv_sqrt2(mouse_report.x); bl mouse_report.x = 1; cmp r0, #0 it eq moveq r0, #1 strb r0, [r4, #2] mouse_report.y = times_inv_sqrt2(mouse_report.y); mov r0, r2 bl if (mouse_report.y == 0) { cbz r0, mouse_report.y = times_inv_sqrt2(mouse_report.y); strb r0, [r4, #3] b.n mouse_report.y = 1; movs r3, #1 strb r3, [r4, #3] b.n if ((tmpmr.v || tmpmr.h) && timer_elapsed(last_timer_w) > (mousekey_wheel_repeat ? mk_wheel_interval : mk_wheel_delay * 10)) { ldr r2, [pc, #144] @ () ldrb r2, [r2, #0] add.w r2, r2, r2, lsl #2 cmp.w r0, r2, lsl #1 ble.n if (mousekey_wheel_repeat != UINT8_MAX) mousekey_wheel_repeat++; adds r3, #1 strb r3, [r1, #0] b.n cmp r3, #255 @ 0xff bne.n if (tmpmr.v != 0) mouse_report.v = wheel_unit() * ((tmpmr.v > 0) ? 1 : -1); ldrsb.w r5, [sp, #4] cbz r5, bl cmp r5, #0 ite le movle r3, #255 @ 0xff movgt r3, #1 muls r3, r0 strb r3, [r4, #4] if (tmpmr.h != 0) mouse_report.h = wheel_unit() * ((tmpmr.h > 0) ? 1 : -1); ldrsb.w r5, [sp, #5] cbz r5, bl cmp r5, #0 ite le movle r3, #255 @ 0xff movgt r3, #1 muls r3, r0 strb r3, [r4, #5] if (mouse_report.v && mouse_report.h) { ldrsb.w r0, [r4, #4] cmp r0, #0 beq.n ldrsb.w r2, [r4, #5] cmp r2, #0 beq.n mouse_report.v = times_inv_sqrt2(mouse_report.v); bl mouse_report.v = 1; cmp r0, #0 it eq moveq r0, #1 strb r0, [r4, #4] mouse_report.h = times_inv_sqrt2(mouse_report.h); mov r0, r2 bl if (mouse_report.h == 0) { cbz r0, mouse_report.h = times_inv_sqrt2(mouse_report.h); strb r0, [r4, #5] b.n mouse_report.h = 1; movs r3, #1 strb r3, [r4, #5] b.n nop .word 0x2000113d .word 0x20001138 .word 0x2000113b .word 0x20000c12 .word 0x20001136 .word 0x2000113a .word 0x20000c0e .word 0x20000c13 .word 0x20000c0f : static uint16_t sc_timer = 0; #ifdef SPACE_CADET_MODIFIER_CARRYOVER static uint8_t sc_mods = 0; #endif void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) { push {r3, r4, r5, r6, r7, lr} mov r4, r2 if (record->event.pressed) { ldrb r2, [r0, #5] void perform_space_cadet(keyrecord_t *record, uint16_t sc_keycode, uint8_t holdMod, uint8_t tapMod, uint8_t keycode) { ldrb.w r7, [sp, #24] mov r5, r3 ldr r3, [pc, #160] @ () if (record->event.pressed) { cbz r2, sc_last = holdMod; strb r4, [r3, #0] sc_timer = timer_read(); bl ldr r3, [pc, #156] @ () strh r0, [r3, #0] #ifdef SPACE_CADET_MODIFIER_CARRYOVER sc_mods = get_mods(); #endif if (IS_MODIFIER_KEYCODE(holdMod)) { add.w r3, r4, #32 uxtb r3, r3 cmp r3, #7 bhi.n register_mods(MOD_BIT(holdMod)); and.w r4, r4, #7 movs r0, #1 lsls r0, r4 uxtb r0, r0 if (IS_MODIFIER_KEYCODE(holdMod)) { unregister_mods(MOD_BIT(holdMod)); } } } } ldmia.w sp!, {r3, r4, r5, r6, r7, lr} register_mods(MOD_BIT(holdMod)); b.w if (sc_last == holdMod && timer_elapsed(sc_timer) < GET_TAPPING_TERM(sc_keycode, record)) { ldrb r6, [r3, #0] cmp r6, r4 bne.n ldr r3, [pc, #116] @ () ldrh r0, [r3, #0] bl cmp r0, #199 @ 0xc7 bhi.n if (holdMod != tapMod) { cmp r6, r5 add.w r4, r5, #32 beq.n if (IS_MODIFIER_KEYCODE(holdMod)) { add.w r3, r6, #32 uxtb r3, r3 cmp r3, #7 bhi.n unregister_mods(MOD_BIT(holdMod)); and.w r6, r6, #7 movs r0, #1 lsls r0, r6 uxtb r0, r0 bl if (IS_MODIFIER_KEYCODE(tapMod)) { uxtb r3, r4 cmp r3, #7 bhi.n register_mods(MOD_BIT(tapMod)); and.w r3, r5, #7 movs r0, #1 lsls r0, r3 uxtb r0, r0 bl tap_code(keycode); mov r0, r7 if (IS_MODIFIER_KEYCODE(tapMod)) { uxtb r4, r4 tap_code(keycode); bl if (IS_MODIFIER_KEYCODE(tapMod)) { cmp r4, #7 bhi.n unregister_mods(MOD_BIT(tapMod)); and.w r5, r5, #7 movs r0, #1 lsls r0, r5 } ldmia.w sp!, {r3, r4, r5, r6, r7, lr} unregister_mods(MOD_BIT(holdMod)); uxtb r0, r0 b.w if (IS_MODIFIER_KEYCODE(holdMod)) { add.w r3, r4, #32 uxtb r3, r3 cmp r3, #7 bhi.n unregister_mods(MOD_BIT(holdMod)); and.w r4, r4, #7 movs r0, #1 lsls r0, r4 b.n } pop {r3, r4, r5, r6, r7, pc} .word 0x20001146 .word 0x20001144 : bool process_space_cadet(uint16_t keycode, keyrecord_t *record) { mov r3, r0 switch (keycode) { sub.w r3, r3, #31744 @ 0x7c00 subs r3, #24 bool process_space_cadet(uint16_t keycode, keyrecord_t *record) { push {r0, r1, r2, lr} mov r0, r1 switch (keycode) { cmp r3, #6 bhi.n tbb [pc, r3] .word 0x10041e17 .short 0x2c25 .byte 0x33 .byte 0x00 case QK_SPACE_CADET_LEFT_SHIFT_PARENTHESIS_OPEN: { perform_space_cadet(record, keycode, LSPO_KEYS); movs r3, #38 @ 0x26 str r3, [sp, #0] movs r3, #225 @ 0xe1 mov r2, r3 movw r1, #31770 @ 0x7c1a return false; } case QK_SPACE_CADET_RIGHT_SHIFT_PARENTHESIS_CLOSE: { perform_space_cadet(record, keycode, RSPC_KEYS); bl return false; movs r0, #0 } break; } } return true; } add sp, #12 ldr.w pc, [sp], #4 perform_space_cadet(record, keycode, RSPC_KEYS); movs r3, #39 @ 0x27 str r3, [sp, #0] movs r3, #229 @ 0xe5 mov r2, r3 movw r1, #31771 @ 0x7c1b b.n perform_space_cadet(record, keycode, LCPO_KEYS); movs r3, #38 @ 0x26 str r3, [sp, #0] movs r2, #224 @ 0xe0 movs r3, #225 @ 0xe1 movw r1, #31768 @ 0x7c18 b.n perform_space_cadet(record, keycode, RCPC_KEYS); movs r3, #39 @ 0x27 str r3, [sp, #0] movs r2, #228 @ 0xe4 movs r3, #229 @ 0xe5 movw r1, #31769 @ 0x7c19 b.n perform_space_cadet(record, keycode, LAPO_KEYS); movs r3, #38 @ 0x26 str r3, [sp, #0] movs r2, #226 @ 0xe2 movs r3, #225 @ 0xe1 movw r1, #31772 @ 0x7c1c b.n perform_space_cadet(record, keycode, RAPC_KEYS); movs r3, #39 @ 0x27 str r3, [sp, #0] movs r2, #230 @ 0xe6 movs r3, #229 @ 0xe5 movw r1, #31773 @ 0x7c1d b.n perform_space_cadet(record, keycode, SFTENT_KEYS); movs r3, #40 @ 0x28 str r3, [sp, #0] movs r2, #229 @ 0xe5 movs r3, #1 movw r1, #31774 @ 0x7c1e b.n if (record->event.pressed) { ldrb r3, [r1, #5] cbz r3, void reset_space_cadet() { sc_last = 0; ldr r3, [pc, #8] @ () movs r2, #0 strb r2, [r3, #0] return true; movs r0, #1 b.n nop .word 0x20001146 : static host_driver_t *driver; static uint16_t last_system_usage = 0; static uint16_t last_consumer_usage = 0; void host_set_driver(host_driver_t *d) { driver = d; ldr r3, [pc, #4] @ () str r0, [r3, #0] } bx lr nop .word 0x2000114c : uint8_t host_keyboard_leds(void) { #ifdef SPLIT_KEYBOARD if (!is_keyboard_master()) return split_led_state; #endif if (!driver) return 0; ldr r3, [pc, #8] @ () ldr r0, [r3, #0] cbz r0, return (*driver->keyboard_leds)(); ldr r3, [r0, #0] bx r3 } bx lr .word 0x2000114c : led_t host_keyboard_led_state(void) { push {r3, lr} return (led_t)host_keyboard_leds(); bl } pop {r3, pc} : bluetooth_send_keyboard(report); return; } #endif if (!driver) return; ldr r3, [pc, #8] @ () ldr r3, [r3, #0] cbz r3, #ifdef KEYBOARD_SHARED_EP report->report_id = REPORT_ID_KEYBOARD; #endif (*driver->send_keyboard)(report); ldr r3, [r3, #4] bx r3 for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { dprintf("%02X ", report->keys[i]); } dprint("\n"); } } bx lr .word 0x2000114c : void host_nkro_send(report_nkro_t *report) { if (!driver) return; ldr r2, [pc, #12] @ () ldr r2, [r2, #0] cbz r2, report->report_id = REPORT_ID_NKRO; movs r1, #6 strb r1, [r0, #0] (*driver->send_nkro)(report); ldr r3, [r2, #8] bx r3 for (uint8_t i = 0; i < NKRO_REPORT_BITS; i++) { dprintf("%02X ", report->bits[i]); } dprint("\n"); } } bx lr .word 0x2000114c : bluetooth_send_mouse(report); return; } #endif if (!driver) return; ldr r2, [pc, #12] @ () ldr r2, [r2, #0] cbz r2, #ifdef MOUSE_SHARED_EP report->report_id = REPORT_ID_MOUSE; movs r1, #2 strb r1, [r0, #0] #ifdef MOUSE_EXTENDED_REPORT // clip and copy to Boot protocol XY report->boot_x = (report->x > 127) ? 127 : ((report->x < -127) ? -127 : report->x); report->boot_y = (report->y > 127) ? 127 : ((report->y < -127) ? -127 : report->y); #endif (*driver->send_mouse)(report); ldr r3, [r2, #12] bx r3 } bx lr .word 0x2000114c : void host_system_send(uint16_t usage) { if (usage == last_system_usage) return; ldr r3, [pc, #44] @ () void host_system_send(uint16_t usage) { push {r0, r1, r2, lr} if (usage == last_system_usage) return; ldrh r2, [r3, #0] cmp r2, r0 beq.n last_system_usage = usage; strh r0, [r3, #0] if (!driver) return; ldr r3, [pc, #36] @ () ldr r3, [r3, #0] cbz r3, report_extra_t report = { movs r2, #3 strb.w r0, [sp, #5] lsrs r0, r0, #8 strb.w r0, [sp, #6] .report_id = REPORT_ID_SYSTEM, .usage = usage, }; (*driver->send_extra)(&report); ldr r3, [r3, #16] report_extra_t report = { strb.w r2, [sp, #4] (*driver->send_extra)(&report); add r0, sp, #4 blx r3 } add sp, #12 ldr.w pc, [sp], #4 nop .word 0x2000114a .word 0x2000114c : void host_consumer_send(uint16_t usage) { if (usage == last_consumer_usage) return; ldr r3, [pc, #44] @ () void host_consumer_send(uint16_t usage) { push {r0, r1, r2, lr} if (usage == last_consumer_usage) return; ldrh r2, [r3, #0] cmp r2, r0 beq.n last_consumer_usage = usage; strh r0, [r3, #0] bluetooth_send_consumer(usage); return; } #endif if (!driver) return; ldr r3, [pc, #36] @ () ldr r3, [r3, #0] cbz r3, report_extra_t report = { movs r2, #4 strb.w r0, [sp, #5] lsrs r0, r0, #8 strb.w r0, [sp, #6] .report_id = REPORT_ID_CONSUMER, .usage = usage, }; (*driver->send_extra)(&report); ldr r3, [r3, #16] report_extra_t report = { strb.w r2, [sp, #4] (*driver->send_extra)(&report); add.w r0, sp, r2 blx r3 } add sp, #12 ldr.w pc, [sp], #4 .word 0x20001148 .word 0x2000114c : /** \brief has_anykey * * FIXME: Needs doc */ uint8_t has_anykey(void) { push {r4, lr} uint8_t cnt = 0; uint8_t* p = keyboard_report->keys; ldr r3, [pc, #60] @ () uint8_t lp = sizeof(keyboard_report->keys); #ifdef NKRO_ENABLE if (keyboard_protocol && keymap_config.nkro) { ldr r2, [pc, #60] @ () uint8_t* p = keyboard_report->keys; ldr r3, [r3, #0] if (keyboard_protocol && keymap_config.nkro) { ldrb r2, [r2, #0] uint8_t* p = keyboard_report->keys; adds r3, #2 if (keyboard_protocol && keymap_config.nkro) { cbz r2, ldr r2, [pc, #56] @ () ldrsb.w r2, [r2] cmp r2, #0 bge.n p = nkro_report->bits; ldr r3, [pc, #48] @ () ldr r3, [r3, #0] lp = sizeof(nkro_report->bits); movs r4, #30 p = nkro_report->bits; adds r3, #2 uint8_t lp = sizeof(keyboard_report->keys); mov r1, r3 movs r0, #0 } #endif while (lp--) { if (*p++) cnt++; ldrb.w r2, [r1], #1 cbz r2, adds r0, #1 uxtb r0, r0 while (lp--) { subs r2, r4, r1 uxtab r2, r3, r2 uxtb r2, r2 cmp r2, #0 bne.n } return cnt; } pop {r4, pc} uint8_t lp = sizeof(keyboard_report->keys); movs r4, #6 b.n .word 0x20000c04 .word 0x20000c14 .word 0x20002048 .word 0x20000c00 : * * Returns true if the keyboard_report reports that the key is pressed, otherwise false * Note: The function doesn't support modifers currently, and it returns false for KC_NO */ bool is_key_pressed(uint8_t key) { if (key == KC_NO) { cbz r0, return false; } #ifdef NKRO_ENABLE if (keyboard_protocol && keymap_config.nkro) { ldr r3, [pc, #80] @ () ldrb r3, [r3, #0] cbz r3, ldr r3, [pc, #76] @ () ldrsb.w r3, [r3] cmp r3, #0 bge.n if ((key >> 3) < NKRO_REPORT_BITS) { cmp r0, #239 @ 0xef mov.w r2, r0, lsr #3 bhi.n return nkro_report->bits[key >> 3] & 1 << (key & 7); ldr r3, [pc, #64] @ () ldr r3, [r3, #0] add r3, r2 and.w r0, r0, #7 ldrb r2, [r3, #2] movs r3, #1 lsl.w r0, r3, r0 tst r2, r0 ite ne movne r0, r3 moveq r0, #0 bx lr return false; } } #endif for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { if (keyboard_report->keys[i] == key) { ldr r3, [pc, #40] @ () ldr r3, [r3, #0] adds r2, r3, #1 adds r3, #7 ldrb.w r1, [r2, #1]! cmp r1, r0 beq.n for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { cmp r2, r3 bne.n return false; movs r0, #0 bx lr return true; movs r0, #1 } } return false; } bx lr nop .word 0x20000c14 .word 0x20002048 .word 0x20000c00 .word 0x20000c04 : /** \brief add key byte * * FIXME: Needs doc */ void add_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { push {r4, r5, lr} movs r2, #0 adds r4, r0, #1 keyboard_report->keys[cb_tail] = code; cb_tail = RO_INC(cb_tail); cb_count++; #else int8_t i = 0; int8_t empty = -1; mov.w r3, #4294967295 @ 0xffffffff for (; i < KEYBOARD_REPORT_KEYS; i++) { if (keyboard_report->keys[i] == code) { ldrb.w r5, [r4, #1]! cmp r5, r1 beq.n break; } if (empty == -1 && keyboard_report->keys[i] == 0) { cmp.w r3, #4294967295 @ 0xffffffff bne.n cbnz r5, sxtb r3, r2 for (; i < KEYBOARD_REPORT_KEYS; i++) { adds r2, #1 cmp r2, #6 bne.n empty = i; } } if (i == KEYBOARD_REPORT_KEYS) { if (empty != -1) { adds r2, r3, #1 beq.n keyboard_report->keys[empty] = code; add r0, r3 strb r1, [r0, #2] } } #endif } pop {r4, r5, pc} : /** \brief del key byte * * FIXME: Needs doc */ void del_key_byte(report_keyboard_t* keyboard_report, uint8_t code) { push {r4, lr} adds r3, r0, #1 } while (i != cb_tail); } #else for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { if (keyboard_report->keys[i] == code) { keyboard_report->keys[i] = 0; movs r2, #0 adds r0, #7 if (keyboard_report->keys[i] == code) { ldrb.w r4, [r3, #1]! cmp r4, r1 keyboard_report->keys[i] = 0; it eq strbeq r2, [r3, #0] for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) { cmp r3, r0 bne.n } } #endif } pop {r4, pc} : /** \brief add key bit * * FIXME: Needs doc */ void add_key_bit(report_nkro_t* nkro_report, uint8_t code) { if ((code >> 3) < NKRO_REPORT_BITS) { cmp r1, #239 @ 0xef mov.w r3, r1, lsr #3 bhi.n nkro_report->bits[code >> 3] |= 1 << (code & 7); add r0, r3 and.w r1, r1, #7 ldrb r2, [r0, #2] movs r3, #1 lsls r3, r1 orrs r3, r2 strb r3, [r0, #2] } else { dprintf("add_key_bit: can't add: %02X\n", code); } } bx lr : /** \brief del key bit * * FIXME: Needs doc */ void del_key_bit(report_nkro_t* nkro_report, uint8_t code) { if ((code >> 3) < NKRO_REPORT_BITS) { cmp r1, #239 @ 0xef mov.w r3, r1, lsr #3 bhi.n nkro_report->bits[code >> 3] &= ~(1 << (code & 7)); add r0, r3 and.w r1, r1, #7 ldrb r3, [r0, #2] movs r2, #1 lsls r2, r1 bic.w r3, r3, r2 strb r3, [r0, #2] } else { dprintf("del_key_bit: can't del: %02X\n", code); } } bx lr ... : * * FIXME: Needs doc */ void add_key_to_report(uint8_t key) { #ifdef NKRO_ENABLE if (keyboard_protocol && keymap_config.nkro) { ldr r3, [pc, #32] @ () ldrb r3, [r3, #0] void add_key_to_report(uint8_t key) { mov r1, r0 if (keyboard_protocol && keymap_config.nkro) { cbz r3, ldr r3, [pc, #28] @ () ldrsb.w r3, [r3] cmp r3, #0 bge.n add_key_bit(nkro_report, key); ldr r3, [pc, #24] @ () ldr r0, [r3, #0] b.w return; } #endif add_key_byte(keyboard_report, key); ldr r3, [pc, #20] @ () ldr r0, [r3, #0] b.w nop .word 0x20000c14 .word 0x20002048 .word 0x20000c00 .word 0x20000c04 : * * FIXME: Needs doc */ void del_key_from_report(uint8_t key) { #ifdef NKRO_ENABLE if (keyboard_protocol && keymap_config.nkro) { ldr r3, [pc, #32] @ () ldrb r3, [r3, #0] void del_key_from_report(uint8_t key) { mov r1, r0 if (keyboard_protocol && keymap_config.nkro) { cbz r3, ldr r3, [pc, #28] @ () ldrsb.w r3, [r3] cmp r3, #0 bge.n del_key_bit(nkro_report, key); ldr r3, [pc, #24] @ () ldr r0, [r3, #0] b.w return; } #endif del_key_byte(keyboard_report, key); ldr r3, [pc, #20] @ () ldr r0, [r3, #0] b.w nop .word 0x20000c14 .word 0x20002048 .word 0x20000c00 .word 0x20000c04 : * FIXME: Needs doc */ void clear_keys_from_report(void) { // not clear mods #ifdef NKRO_ENABLE if (keyboard_protocol && keymap_config.nkro) { ldr r3, [pc, #36] @ () ldrb r3, [r3, #0] cbz r3, ldr r3, [pc, #36] @ () ldrsb.w r3, [r3] cmp r3, #0 bge.n memset(nkro_report->bits, 0, sizeof(nkro_report->bits)); ldr r3, [pc, #28] @ () ldr r0, [r3, #0] movs r2, #30 return; } #endif memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys)); movs r1, #0 adds r0, #2 b.w ldr r3, [pc, #20] @ () movs r2, #6 ldr r0, [r3, #0] b.n nop .word 0x20000c14 .word 0x20002048 .word 0x20000c00 .word 0x20000c04 : // shared mouse endpoint bool changed = ((new_report->buttons != old_report->buttons) || # ifdef MOUSE_EXTENDED_REPORT (new_report->boot_x != 0 && new_report->boot_x != old_report->boot_x) || (new_report->boot_y != 0 && new_report->boot_y != old_report->boot_y) || # endif (new_report->x != 0 && new_report->x != old_report->x) || (new_report->y != 0 && new_report->y != old_report->y) || (new_report->h != 0 && new_report->h != old_report->h) || (new_report->v != 0 && new_report->v != old_report->v)); ldrb r2, [r0, #1] ldrb r3, [r1, #1] cmp r2, r3 bne.n ldrsb.w r3, [r0, #2] bool changed = ((new_report->buttons != old_report->buttons) || cbz r3, (new_report->x != 0 && new_report->x != old_report->x) || (new_report->y != 0 && new_report->y != old_report->y) || (new_report->h != 0 && new_report->h != old_report->h) || (new_report->v != 0 && new_report->v != old_report->v)); ldrsb.w r2, [r1, #2] cmp r2, r3 bne.n ldrsb.w r3, [r0, #3] cbz r3, ldrsb.w r2, [r1, #3] cmp r2, r3 bne.n ldrsb.w r3, [r0, #5] cbz r3, ldrsb.w r2, [r1, #5] cmp r2, r3 bne.n ldrsb.w r0, [r0, #4] cbz r0, ldrsb.w r3, [r1, #4] subs r0, r3, r0 it ne movne r0, #1 bx lr movs r0, #1 return changed; } bx lr : __attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); } __attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} bx lr : __attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { push {r3, lr} notify_usb_device_state_change_user(usb_device_state); bl } pop {r3, pc} ... : haptic_notify_usb_device_state_change(); #endif notify_usb_device_state_change_kb(usb_device_state); } void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { push {r3, lr} adds r0, #1 usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; ldr r3, [pc, #8] @ () uxtb r0, r0 strb r0, [r3, #0] notify_usb_device_state_change_kb(usb_device_state); bl notify_usb_device_state_change(usb_device_state); } pop {r3, pc} .word 0x20001150 : void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { push {r3, lr} usb_device_state = USB_DEVICE_STATE_SUSPEND; ldr r3, [pc, #12] @ () movs r0, #3 strb r0, [r3, #0] notify_usb_device_state_change_kb(usb_device_state); bl notify_usb_device_state_change(usb_device_state); } pop {r3, pc} nop .word 0x20001150 : void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { b.w : usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; notify_usb_device_state_change(usb_device_state); } void usb_device_state_set_reset(void) { push {r3, lr} usb_device_state = USB_DEVICE_STATE_INIT; ldr r3, [pc, #12] @ () movs r0, #1 strb r0, [r3, #0] notify_usb_device_state_change_kb(usb_device_state); bl notify_usb_device_state_change(usb_device_state); } pop {r3, pc} nop .word 0x20001150 : void usb_device_state_init(void) { b.w : #include "suspend.h" #include "matrix.h" // TODO: Move to more correct location __attribute__((weak)) void matrix_power_up(void) {} bx lr : __attribute__((weak)) void matrix_power_down(void) {} bx lr : /** \brief Run user level Power down * * FIXME: needs doc */ __attribute__((weak)) void suspend_power_down_user(void) {} bx lr : /** \brief Run keyboard level Power down * * FIXME: needs doc */ __attribute__((weak)) void suspend_power_down_kb(void) { push {r3, lr} suspend_power_down_user(); bl } pop {r3, pc} : /** \brief run user level code immediately after wakeup * * FIXME: needs doc */ __attribute__((weak)) void suspend_wakeup_init_user(void) {} bx lr : /** \brief run keyboard level code immediately after wakeup * * FIXME: needs doc */ __attribute__((weak)) void suspend_wakeup_init_kb(void) { push {r3, lr} suspend_wakeup_init_user(); bl } pop {r3, pc} : /** \brief suspend wakeup condition * * FIXME: needs doc */ bool suspend_wakeup_condition(void) { push {r4, lr} matrix_power_up(); bl matrix_scan(); bl matrix_power_down(); bl movs r4, #0 for (uint8_t r = 0; r < MATRIX_ROWS; r++) { if (matrix_get_row(r)) return true; uxtb r0, r4 bl cbnz r0, for (uint8_t r = 0; r < MATRIX_ROWS; r++) { adds r4, #1 cmp r4, #15 bne.n } return false; } pop {r4, pc} if (matrix_get_row(r)) return true; movs r0, #1 b.n : * along with this program. If not, see . */ #include "platform_deps.h" void platform_setup(void) { push {r3, lr} halInit(); bl chSysInit(); ldmia.w sp!, {r3, lr} chSysInit(); b.w : /** \brief suspend power down * * FIXME: needs doc */ void suspend_power_down(void) { push {r3, lr} suspend_power_down_quantum(); bl // on AVR, this enables the watchdog for 15ms (max), and goes to // SLEEP_MODE_PWR_DOWN wait_ms(17); } ldmia.w sp!, {r3, lr} wait_ms(17); movs r0, #170 @ 0xaa b.w : /** \brief suspend wakeup condition * * run immediately after wakeup * FIXME: needs doc */ void suspend_wakeup_init(void) { push {r3, lr} // need to do it manually, because we're running from ISR // and clear_keyboard() calls print // so only clear the variables in memory // the reports will be sent from main.c afterwards // or if the PC asks for GET_REPORT clear_mods(); bl clear_weak_mods(); bl clear_keys_from_report(); bl clear_keys(); #ifdef MOUSEKEY_ENABLE mousekey_clear(); bl #endif /* MOUSEKEY_ENABLE */ #ifdef PROGRAMMABLE_BUTTON_ENABLE programmable_button_clear(); #endif /* PROGRAMMABLE_BUTTON_ENABLE */ #ifdef EXTRAKEY_ENABLE host_system_send(0); movs r0, #0 bl host_consumer_send(0); movs r0, #0 bl #endif /* EXTRAKEY_ENABLE */ suspend_wakeup_init_quantum(); } ldmia.w sp!, {r3, lr} suspend_wakeup_init_quantum(); b.w : movs r3, #48 @ 0x30 msr BASEPRI, r3 * @xclass */ static inline systime_t chVTGetSystemTimeX(void) { #if CH_CFG_ST_TIMEDELTA == 0 return currcore->vtlist.systime; ldr r3, [pc, #24] @ () ldr r2, [r3, #28] #endif } void timer_clear(void) { chSysLock(); ticks_offset = get_system_time_ticks(); ldr r3, [pc, #24] @ () str r2, [r3, #0] last_ticks = 0; ldr r2, [pc, #24] @ () movs r3, #0 str r3, [r2, #0] ms_offset = 0; ldr r2, [pc, #20] @ () str r3, [r2, #0] msr BASEPRI, r3 chSysUnlock(); } bx lr nop .word 0x20002090 .word 0x2000115c .word 0x20001158 .word 0x20001154 : timer_clear(); b.w : uint16_t timer_read(void) { return (uint16_t)timer_read32(); } uint32_t timer_read32(void) { push {r4, r5, r6, lr} movs r3, #48 @ 0x30 msr BASEPRI, r3 ldr r3, [pc, #72] @ () chSysLock(); uint32_t ticks = get_system_time_ticks() - ticks_offset; ldr r0, [pc, #76] @ () if (ticks < last_ticks) { ldr r1, [pc, #76] @ () ldr r4, [r3, #28] uint32_t ticks = get_system_time_ticks() - ticks_offset; ldr r3, [r0, #0] if (ticks < last_ticks) { ldr r2, [r1, #0] uint32_t ticks = get_system_time_ticks() - ticks_offset; subs r4, r4, r3 if (ticks < last_ticks) { cmp r2, r4 ldr r2, [pc, #68] @ () bls.n // to subtract a reasonably large number of ticks from the tick counter to bring its value below the 32-bit // limit again, and then add the equivalent number of milliseconds to the converted value. (Adjusting just the // converted value to account for 2**32 ticks is not possible in general, because 2**32 ticks may not correspond // to an integer number of milliseconds). ticks -= OVERFLOW_ADJUST_TICKS; ticks_offset += OVERFLOW_ADJUST_TICKS; sub.w r3, r3, #7296 @ 0x1c80 str r3, [r0, #0] ms_offset += OVERFLOW_ADJUST_MS; ldr r0, [r2, #0] ldr r3, [pc, #60] @ () add r3, r0 ticks -= OVERFLOW_ADJUST_TICKS; add.w r4, r4, #7296 @ 0x1c80 ms_offset += OVERFLOW_ADJUST_MS; str r3, [r2, #0] } last_ticks = ticks; str r4, [r1, #0] uint32_t ms_offset_copy = ms_offset; // read while still holding the lock to ensure a consistent value ldr r6, [r2, #0] movs r1, #0 msr BASEPRI, r1 chSysUnlock(); return (uint32_t)TIME_I2MS(ticks) + ms_offset_copy; mov.w r5, #1000 @ 0x3e8 movw r0, #9999 @ 0x270f movw r2, #10000 @ 0x2710 movs r3, #0 umlal r0, r1, r4, r5 bl <__aeabi_uldivmod> } add r0, r6 pop {r4, r5, r6, pc} nop .word 0x20002090 .word 0x2000115c .word 0x20001158 .word 0x20001154 .word 0x199996c0 : uint16_t timer_read(void) { push {r3, lr} return (uint16_t)timer_read32(); bl } uxth r0, r0 pop {r3, pc} : uint16_t timer_elapsed(uint16_t last) { push {r4, lr} mov r4, r0 return (uint16_t)timer_read32(); bl return TIMER_DIFF_16(timer_read(), last); subs r0, r0, r4 } uxth r0, r0 pop {r4, pc} : #include "bootloader.h" #include #include "wait.h" __attribute__((weak)) void bootloader_jump(void) { push {r3, lr} wait_ms(100); mov.w r0, #1000 @ 0x3e8 bl __BKPT(0); bkpt 0x0000 } pop {r3, pc} : __attribute__((weak)) void mcu_reset(void) {} bx lr : * callback pointer is NULL. */ static void dummy_usb_cb(USBDriver *usbp, usbep_t ep) { (void)usbp; (void)ep; } bx lr : movs r3, #48 @ 0x30 msr BASEPRI, r3 movs r3, #0 msr BASEPRI, r3 osalSysLockFromISR(); for (int i = 0; i < NUM_USB_DRIVERS; i++) { qmkusbSOFHookI(&drivers.array[i].driver); } osalSysUnlockFromISR(); } bx lr : static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t wIndex) { push {r3, r4, r5, r6, r7, lr} descriptor.ud_string = NULL; ldr r4, [pc, #60] @ () mov r3, r4 movs r2, #0 str.w r2, [r3, #4]! descriptor.ud_size = get_usb_descriptor(setup->wValue.word, setup->wIndex, setup->wLength, (const void **const) & descriptor.ud_string); ldrb.w r7, [r0, #123] @ 0x7b ldrb.w r6, [r0, #121] @ 0x79 ldrb.w r5, [r0, #118] @ 0x76 ldrb.w r2, [r0, #122] @ 0x7a ldrb.w r1, [r0, #120] @ 0x78 ldrb.w r0, [r0, #119] @ 0x77 orr.w r2, r2, r7, lsl #8 orr.w r1, r1, r6, lsl #8 orr.w r0, r5, r0, lsl #8 bl str r0, [r4, #0] if (descriptor.ud_string == NULL) { ldr r0, [r4, #4] return &descriptor; cmp r0, #0 } it ne movne r0, r4 pop {r3, r4, r5, r6, r7, pc} .word 0x20001160 : if (setup->wLength == 2) { ldrb.w r2, [r0, #122] @ 0x7a ldrb.w r0, [r0, #123] @ 0x7b uint8_t report_id = set_report_buf[0]; ldr r1, [pc, #32] @ () if (setup->wLength == 2) { orr.w r2, r2, r0, lsl #8 cmp r2, #2 uint8_t report_id = set_report_buf[0]; ldrb r3, [r1, #0] if (setup->wLength == 2) { bne.n if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) { cmp r3, #1 beq.n cmp r3, #6 bne.n keyboard_led_state = set_report_buf[1]; ldr r3, [pc, #16] @ () ldrb r2, [r1, #1] strb r2, [r3, #0] } bx lr keyboard_led_state = set_report_buf[0]; ldr r2, [pc, #8] @ () strb r3, [r2, #0] } bx lr nop .word 0x20001168 .word 0x200011bc : * @param[in] par a parameter that will be passed to the callback * function * * @iclass */ static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay, push {r4, r5, r6, lr} mov r4, r0 return (bool)(vtp->dlist.next != NULL); ldr r0, [pc, #24] @ () if (chVTIsArmedI(vtp)) { ldr r3, [r0, #0] static inline void chVTSetI(virtual_timer_t *vtp, sysinterval_t delay, mov r5, r1 if (chVTIsArmedI(vtp)) { cbz r3, chVTDoResetI(vtp); bl vtfunc_t vtfunc, void *par) { chVTResetI(vtp); chVTDoSetI(vtp, delay, vtfunc, par); mov r3, r5 mov r1, r4 ldr r2, [pc, #12] @ () ldr r0, [pc, #8] @ () } ldmia.w sp!, {r4, r5, r6, lr} chVTDoSetI(vtp, delay, vtfunc, par); b.w .word 0x200011a4 .word 0x6000490d : * --------------------------------------------------------- */ /* Idle requests timer code * callback (called from ISR, unlocked state) */ static void keyboard_idle_timer_cb(struct ch_virtual_timer *timer, void *arg) { push {r3, r4, r5, lr} mov r4, r1 movs r3, #48 @ 0x30 msr BASEPRI, r3 USBDriver *usbp = (USBDriver *)arg; osalSysLockFromISR(); /* check that the states of things are as they're supposed to */ if (usbGetDriverStateI(usbp) != USB_ACTIVE) { ldrb r3, [r1, #0] cmp r3, #4 beq.n movs r3, #0 msr BASEPRI, r3 } /* do not rearm the timer if the condition above fails * it should be enabled again on either IDLE or SET_PROTOCOL requests */ osalSysUnlockFromISR(); } pop {r3, r4, r5, pc} if (!keymap_config.nkro && keyboard_idle && keyboard_protocol) { ldr r3, [pc, #76] @ () ldrb r3, [r3, #0] lsrs r3, r3, #7 bne.n ldr r5, [pc, #72] @ () ldrb r3, [r5, #0] cmp r3, #0 beq.n ldr r3, [pc, #68] @ () ldrb r3, [r3, #0] cmp r3, #0 beq.n if (!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) { ldrh r3, [r1, #8] lsls r3, r3, #30 bmi.n usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE); ldr r2, [pc, #60] @ () movs r3, #8 movs r1, #1 mov r0, r4 bl chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); ldrb r0, [r5, #0] movw r3, #10000 @ 0x2710 umull r0, r3, r0, r3 mov.w r2, #1000 @ 0x3e8 movs r3, #0 addw r0, r0, #999 @ 0x3e7 movs r1, #0 bl <__aeabi_uldivmod> mov r1, r4 lsls r0, r0, #2 bl b.n nop .word 0x20002048 .word 0x200011be .word 0x20000c14 .word 0x2000119a : static bool usb_requests_hook_cb(USBDriver *usbp) { push {r3, r4, r5, lr} if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) { ldrb.w r2, [r0, #116] @ 0x74 and.w r3, r2, #127 @ 0x7f cmp r3, #33 @ 0x21 static bool usb_requests_hook_cb(USBDriver *usbp) { mov r4, r0 if ((setup->bmRequestType & (USB_RTYPE_TYPE_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_TYPE_CLASS | USB_RTYPE_RECIPIENT_INTERFACE)) { bne.w switch (setup->bmRequestType & USB_RTYPE_DIR_MASK) { tst.w r2, #128 @ 0x80 ldrb.w r3, [r0, #117] @ 0x75 beq.n switch (setup->bRequest) { cmp r3, #2 beq.n cmp r3, #3 beq.n cmp r3, #1 bne.n switch (setup->wIndex) { ldrb.w r3, [r0, #120] @ 0x78 ldrb.w r2, [r0, #121] @ 0x79 orrs.w r3, r3, r2, lsl #8 beq.n cmp r3, #1 ldrb.w r2, [r0, #118] @ 0x76 beq.n universal_report_blank.report_id = setup->wValue.lbyte; ldr r3, [pc, #280] @ () usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL); str r3, [r4, #104] @ 0x68 universal_report_blank.report_id = setup->wValue.lbyte; strb r2, [r3, #0] usbSetupTransfer(usbp, (uint8_t *)&universal_report_blank, setup->wLength, NULL); ldrb.w r3, [r4, #122] @ 0x7a ldrb.w r2, [r4, #123] @ 0x7b orr.w r3, r3, r2, lsl #8 b.n usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, KEYBOARD_REPORT_SIZE, NULL); ldr r2, [pc, #264] @ () str r2, [r0, #104] @ 0x68 movs r2, #8 usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL); str r2, [r4, #108] @ 0x6c b.n if (setup->wValue.lbyte == REPORT_ID_MOUSE) { cmp r2, #2 bne.n usbSetupTransfer(usbp, (uint8_t *)&mouse_report_sent, sizeof(mouse_report_sent), NULL); ldr r3, [pc, #252] @ () str r3, [r0, #104] @ 0x68 movs r3, #6 str r3, [r4, #108] @ 0x6c movs r3, #0 str r3, [r4, #112] @ 0x70 return TRUE; movs r0, #1 } pop {r3, r4, r5, pc} if (setup->wIndex == KEYBOARD_INTERFACE) { ldrb.w r3, [r0, #120] @ 0x78 ldrb.w r1, [r0, #121] @ 0x79 orrs.w r3, r3, r1, lsl #8 bne.n usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL); ldr r2, [pc, #228] @ () str r2, [r0, #104] @ 0x68 movs r2, #1 b.n usbSetupTransfer(usbp, &keyboard_idle, sizeof(uint8_t), NULL); ldr r3, [pc, #224] @ () str r3, [r0, #104] @ 0x68 movs r3, #1 b.n switch (setup->bRequest) { cmp r3, #10 beq.n cmp r3, #11 beq.n cmp r3, #9 bne.n switch (setup->wIndex) { ldrb.w r3, [r0, #120] @ 0x78 ldrb.w r2, [r0, #121] @ 0x79 orr.w r3, r3, r2, lsl #8 cmp r3, #1 bls.n return false; movs r0, #0 b.n usbSetupTransfer(usbp, set_report_buf, sizeof(set_report_buf), set_led_transfer_cb); ldr r3, [pc, #188] @ () str r3, [r0, #104] @ 0x68 movs r3, #2 str r3, [r0, #108] @ 0x6c ldr r3, [pc, #184] @ () b.n if (setup->wIndex == KEYBOARD_INTERFACE) { ldrb.w r3, [r0, #120] @ 0x78 ldrb.w r2, [r0, #121] @ 0x79 orrs.w r3, r3, r2, lsl #8 bne.n keyboard_protocol = setup->wValue.word; ldrb.w r5, [r0, #118] @ 0x76 ldr r3, [pc, #148] @ () strb r5, [r3, #0] if (!keyboard_protocol && keyboard_idle) { cbnz r5, ldr r3, [pc, #148] @ () ldrb r2, [r3, #0] cbz r2, movs r2, #48 @ 0x30 msr BASEPRI, r2 chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); ldrb r0, [r3, #0] movw r3, #10000 @ 0x2710 umull r0, r3, r0, r3 mov.w r2, #1000 @ 0x3e8 movs r3, #0 addw r0, r0, #999 @ 0x3e7 movs r1, #0 bl <__aeabi_uldivmod> mov r1, r4 lsls r0, r0, #2 bl msr BASEPRI, r5 usbSetupTransfer(usbp, NULL, 0, NULL); movs r3, #0 str r3, [r4, #104] @ 0x68 str r3, [r4, #108] @ 0x6c b.n if (!keymap_config.nkro && keyboard_idle) { ldr r1, [pc, #100] @ () keyboard_idle = setup->wValue.hbyte; ldr r3, [pc, #88] @ () if (!keymap_config.nkro && keyboard_idle) { ldrb r1, [r1, #0] keyboard_idle = setup->wValue.hbyte; ldrb.w r2, [r0, #119] @ 0x77 strb r2, [r3, #0] if (!keymap_config.nkro && keyboard_idle) { lsrs r5, r1, #7 bne.n b.n if (((setup->bmRequestType & (USB_RTYPE_DIR_MASK | USB_RTYPE_RECIPIENT_MASK)) == (USB_RTYPE_DIR_DEV2HOST | USB_RTYPE_RECIPIENT_INTERFACE)) && (setup->bRequest == USB_REQ_GET_DESCRIPTOR)) { and.w r2, r2, #159 @ 0x9f cmp r2, #129 @ 0x81 bne.n ldrb.w r3, [r4, #117] @ 0x75 cmp r3, #6 bne.n const USBDescriptor *descriptor = usbp->config->get_descriptor_cb(usbp, setup->wValue.lbyte, setup->wValue.hbyte, setup->wIndex); ldrb.w r2, [r4, #121] @ 0x79 ldr r1, [r4, #4] ldrb.w r3, [r4, #120] @ 0x78 ldr r5, [r1, #4] ldrb.w r1, [r4, #118] @ 0x76 orr.w r3, r3, r2, lsl #8 mov r0, r4 ldrb.w r2, [r4, #119] @ 0x77 blx r5 if (descriptor == NULL) { cmp r0, #0 beq.n usbSetupTransfer(usbp, (uint8_t *)descriptor->ud_string, descriptor->ud_size, NULL); ldr r3, [r0, #4] str r3, [r4, #104] @ 0x68 ldr r3, [r0, #0] b.n nop .word 0x2000118c .word 0x2000119a .word 0x20001194 .word 0x20000c14 .word 0x200011be .word 0x20001168 .word 0x600048b1 .word 0x20002048 : static inline bool usb_event_queue_enqueue(usbevent_t event) { push {r4, lr} uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE; ldr r2, [pc, #24] @ () if (next == event_queue_tail) { ldr r4, [pc, #24] @ () uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE; ldrb r1, [r2, #0] if (next == event_queue_tail) { ldrb r4, [r4, #0] uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE; adds r3, r1, #1 and.w r3, r3, #15 if (next == event_queue_tail) { cmp r4, r3 event_queue[event_queue_head] = event; ittt ne ldrne r4, [pc, #12] @ () event_queue_head = next; strbne r3, [r2, #0] event_queue[event_queue_head] = event; strbne r0, [r4, r1] } pop {r4, pc} .word 0x20002078 .word 0x20002079 .word 0x20002068 : static void usb_event_cb(USBDriver *usbp, usbevent_t event) { push {r4, lr} mov r4, r0 mov r0, r1 switch (event) { cmp r1, #5 bhi.n tbb [pc, r1] .short 0x201a .word 0x1e1a1a03 movs r3, #48 @ 0x30 msr BASEPRI, r3 usbInitEndpointI(usbp, KEYBOARD_IN_EPNUM, &kbd_ep_config); ldr r2, [pc, #52] @ () mov r0, r4 movs r1, #1 bl usbInitEndpointI(usbp, SHARED_IN_EPNUM, &shared_ep_config); ldr r2, [pc, #44] @ () movs r1, #2 mov r0, r4 bl movs r3, #0 msr BASEPRI, r3 if (last_suspend_state) { ldr r3, [pc, #32] @ () ldrb r3, [r3, #0] cbz r3, usb_event_queue_enqueue(USB_EVENT_WAKEUP); movs r0, #5 bl usb_event_queue_enqueue(USB_EVENT_CONFIGURED); movs r0, #2 } ldmia.w sp!, {r4, lr} usb_event_queue_enqueue(USB_EVENT_WAKEUP); b.w movs r0, #5 b.n } pop {r4, pc} .word 0x60008be0 .word 0x60008bbc .word 0x2000116a : void usb_event_queue_init(void) { push {r3, lr} memset(&event_queue, 0, sizeof(event_queue)); movs r2, #16 ldr r0, [pc, #16] @ () movs r1, #0 bl event_queue_head = 0; ldr r2, [pc, #12] @ () movs r3, #0 strb r3, [r2, #0] event_queue_tail = 0; ldr r2, [pc, #12] @ () strb r3, [r2, #0] } pop {r3, pc} .word 0x20002068 .word 0x20002078 .word 0x20002079 : void usb_event_queue_task(void) { push {r3, r4, r5, r6, r7, lr} if (event_queue_head == event_queue_tail) { ldr r5, [pc, #160] @ () ldr r4, [pc, #160] @ () ldrb r6, [r5, #0] ldrb r3, [r4, #0] movs r2, #0 cmp r3, r6 bne.n cbz r2, strb r3, [r4, #0] } pop {r3, r4, r5, r6, r7, pc} strb r3, [r4, #0] last_suspend_state = true; ldr r3, [pc, #144] @ () strb r0, [r3, #0] usb_device_state_set_suspend(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); ldr r3, [pc, #144] @ () ldrb.w r1, [r3, #127] @ 0x7f subs r0, r1, #0 it ne movne r0, #1 bl } b.n strb r3, [r4, #0] last_suspend_state = false; ldr r3, [pc, #120] @ () movs r2, #0 strb r2, [r3, #0] suspend_wakeup_init(); bl usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); ldr r3, [pc, #116] @ () ldrb.w r1, [r3, #127] @ 0x7f subs r0, r1, #0 it ne movne r0, #1 bl } b.n strb r3, [r4, #0] usb_device_state_set_configuration(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); ldr r3, [pc, #96] @ () ldrb.w r1, [r3, #127] @ 0x7f subs r0, r1, #0 it ne movne r0, #1 usb_device_state_set_configuration(false, 0); bl break; b.n usb_device_state_set_configuration(false, 0); movs r1, #0 strb r3, [r4, #0] mov r0, r1 b.n strb r3, [r4, #0] usb_device_state_set_reset(); bl break; b.n *event = event_queue[event_queue_tail]; ldr r0, [pc, #64] @ () mov r1, r3 event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE; movs r2, #1 switch (event) { ldrb r1, [r0, r1] event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE; adds r3, #1 and.w r3, r3, #15 switch (event) { mov r0, r2 cmp r1, #5 bhi.n add r7, pc, #4 @ (adr r7, ) ldr.w pc, [r7, r1, lsl #2] nop .word 0x60004c0d .word 0x60004bb1 .word 0x60004bf1 .word 0x60004c05 .word 0x60004bbb .word 0x60004bd3 .word 0x20002078 .word 0x20002079 .word 0x2000116a .word 0x2000210c .word 0x20002068 : void init_usb_driver(USBDriver *usbp) { push {r3, r4, r5, lr} usbDisconnectBus(usbp); ldr r5, [pc, #56] @ () ldr r3, [r5, #0] movs r2, #0 movs r1, #1 void init_usb_driver(USBDriver *usbp) { mov r4, r0 usbDisconnectBus(usbp); ldr r0, [r3, #8] bl usbStop(usbp); mov r0, r4 bl wait_ms(50); mov.w r0, #500 @ 0x1f4 bl usbStart(usbp, &usbcfg); ldr r1, [pc, #28] @ () mov r0, r4 bl usbConnectBus(usbp); ldr r3, [r5, #0] movs r2, #0 ldr r0, [r3, #8] mov r1, r2 bl vtp->dlist.next = NULL; ldr r3, [pc, #12] @ () movs r2, #0 str r2, [r3, #0] } pop {r3, r4, r5, pc} .word 0x20002108 .word 0x60008bac .word 0x200011a4 : __attribute__((weak)) void restart_usb_driver(USBDriver *usbp) { push {r3, r4, r5, lr} usbDisconnectBus(usbp); ldr r5, [pc, #44] @ () ldr r3, [r5, #0] __attribute__((weak)) void restart_usb_driver(USBDriver *usbp) { mov r4, r0 usbDisconnectBus(usbp); movs r2, #0 ldr r0, [r3, #8] movs r1, #1 bl usbStop(usbp); mov r0, r4 bl usbStart(usbp, &usbcfg); ldr r1, [pc, #24] @ () mov r0, r4 bl usbConnectBus(usbp); ldr r3, [r5, #0] movs r2, #0 ldr r0, [r3, #8] mov r1, r2 } ldmia.w sp!, {r3, r4, r5, lr} usbConnectBus(usbp); b.w .word 0x20002108 .word 0x60008bac : /* LED status */ uint8_t keyboard_leds(void) { return keyboard_led_state; } ldr r3, [pc, #4] @ () ldrb r0, [r3, #0] bx lr nop .word 0x200011bc : void send_report(uint8_t endpoint, void *report, size_t size) { push {r4, r5, r6, lr} movs r3, #48 @ 0x30 mov r4, r0 mov r5, r1 mov r6, r2 msr BASEPRI, r3 osalSysLock(); if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) { ldr r0, [pc, #60] @ () ldrb r3, [r0, #0] cmp r3, #4 beq.n movs r3, #0 msr BASEPRI, r3 return; } } usbStartTransmitI(&USB_DRIVER, endpoint, report, size); osalSysUnlock(); } pop {r4, r5, r6, pc} if (usbGetTransmitStatusI(&USB_DRIVER, endpoint)) { ldrh r2, [r0, #8] movs r3, #1 lsls r3, r4 tst r3, r2 beq.n if (osalThreadSuspendTimeoutS(&(&USB_DRIVER)->epc[endpoint]->in_state->thread, TIME_MS2I(10)) == MSG_TIMEOUT) { add.w r0, r0, r4, lsl #2 * @sclass */ static inline msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) { return chThdSuspendTimeoutS(trp, timeout); movs r1, #100 @ 0x64 ldr r3, [r0, #12] ldr r0, [r3, #20] adds r0, #12 bl adds r0, #1 beq.n usbStartTransmitI(&USB_DRIVER, endpoint, report, size); ldr r0, [pc, #12] @ () mov r3, r6 mov r2, r5 mov r1, r4 bl b.n nop .word 0x2000210c : /* prepare and start sending a report IN * not callable from ISR or locked state */ void send_keyboard(report_keyboard_t *report) { push {r4, lr} /* If we're in Boot Protocol, don't send any report ID or other funky fields */ if (!keyboard_protocol) { send_report(KEYBOARD_IN_EPNUM, &report->mods, 8); mov r1, r0 void send_keyboard(report_keyboard_t *report) { mov r4, r0 send_report(KEYBOARD_IN_EPNUM, &report->mods, 8); movs r2, #8 movs r0, #1 } else { send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE); bl } keyboard_report_sent = *report; movs r2, #8 mov r1, r4 ldr r0, [pc, #8] @ () bl } pop {r4, pc} nop .word 0x2000119a : void send_nkro(report_nkro_t *report) { mov r1, r0 #ifdef NKRO_ENABLE send_report(SHARED_IN_EPNUM, report, sizeof(report_nkro_t)); movs r2, #32 movs r0, #2 b.w ... : /* --------------------------------------------------------- * Mouse functions * --------------------------------------------------------- */ void send_mouse(report_mouse_t *report) { push {r4, lr} #ifdef MOUSE_ENABLE send_report(MOUSE_IN_EPNUM, report, sizeof(report_mouse_t)); mov r1, r0 void send_mouse(report_mouse_t *report) { mov r4, r0 send_report(MOUSE_IN_EPNUM, report, sizeof(report_mouse_t)); movs r2, #6 movs r0, #2 bl mouse_report_sent = *report; movs r2, #6 mov r1, r4 ldr r0, [pc, #8] @ () bl #endif } pop {r4, pc} nop .word 0x20001194 : /* --------------------------------------------------------- * Extrakey functions * --------------------------------------------------------- */ void send_extra(report_extra_t *report) { mov r1, r0 #ifdef EXTRAKEY_ENABLE send_report(SHARED_IN_EPNUM, report, sizeof(report_extra_t)); movs r2, #3 movs r0, #2 b.w : __attribute__((weak)) void early_hardware_init_pre(void) { #if EARLY_INIT_PERFORM_BOOTLOADER_JUMP void enter_bootloader_mode_if_requested(void); enter_bootloader_mode_if_requested(); #endif // EARLY_INIT_PERFORM_BOOTLOADER_JUMP } bx lr : __attribute__((weak)) void early_hardware_init_post(void) {} bx lr : __attribute__((weak)) void board_init(void) {} bx lr <__early_init>: // This overrides what's normally in ChibiOS board definitions void __early_init(void) { push {r3, lr} early_hardware_init_pre(); bl // This is the renamed equivalent of __early_init in the board.c file void __chibios_override___early_init(void); __chibios_override___early_init(); bl <__chibios_override___early_init> early_hardware_init_post(); bl } pop {r3, pc} : // This overrides what's normally in ChibiOS board definitions void boardInit(void) { push {r3, lr} // This is the renamed equivalent of boardInit in the board.c file void __chibios_override_boardInit(void); __chibios_override_boardInit(); bl <__chibios_override_boardInit> board_init(); bl } pop {r3, pc} : void protocol_setup(void) { usb_device_state_init(); b.w : // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); } static host_driver_t *driver = NULL; void protocol_pre_init(void) { push {r3, lr} /* Init USB */ usb_event_queue_init(); bl init_usb_driver(&USB_DRIVER); ldr r0, [pc, #24] @ () bl if (USB_DRIVER.state == USB_ACTIVE) { driver = &chibios_driver; break; } #else driver = &chibios_driver; ldr r3, [pc, #20] @ () ldr r2, [pc, #24] @ () str r2, [r3, #0] /* Do need to wait here! * Otherwise the next print might start a transfer on console EP * before the USB is completely ready, which sometimes causes * HardFaults. */ wait_ms(50); mov.w r0, #500 @ 0x1f4 print("USB configured.\n"); } ldmia.w sp!, {r3, lr} wait_ms(50); b.w nop .word 0x2000210c .word 0x200011c0 .word 0x20000c18 : void protocol_post_init(void) { host_set_driver(driver); ldr r3, [pc, #4] @ () ldr r0, [r3, #0] b.w .word 0x200011c0 : } void protocol_pre_task(void) { push {r4, lr} usb_event_queue_task(); #if !defined(NO_USB_STARTUP_CHECK) if (USB_DRIVER.state == USB_SUSPENDED) { ldr r4, [pc, #64] @ () usb_event_queue_task(); bl if (USB_DRIVER.state == USB_SUSPENDED) { ldrb r3, [r4, #0] cmp r3, #5 bne.n dprintln("suspending keyboard"); while (USB_DRIVER.state == USB_SUSPENDED) { ldrb r3, [r4, #0] cmp r3, #5 beq.n restart_usb_driver(&USB_DRIVER); } } /* Woken up */ // variables has been already cleared by the wakeup hook send_keyboard_report(); bl # ifdef MOUSEKEY_ENABLE mousekey_send(); # endif /* MOUSEKEY_ENABLE */ } #endif } ldmia.w sp!, {r4, lr} mousekey_send(); b.w suspend_power_down(); // on AVR this deep sleeps for 15ms bl if ((USB_DRIVER.status & USB_GETSTATUS_REMOTE_WAKEUP_ENABLED) && suspend_wakeup_condition()) { ldrh.w r3, [r4, #124] @ 0x7c lsls r3, r3, #30 bpl.n bl cmp r0, #0 beq.n usbWakeupHost(&USB_DRIVER); ldr r0, [pc, #12] @ () bl restart_usb_driver(&USB_DRIVER); ldr r0, [pc, #8] @ () bl b.n } pop {r4, pc} .word 0x2000210c : virtser_task(); #endif #ifdef RAW_ENABLE raw_hid_task(); #endif } bx lr ... : * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the * USB host. */ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, const void** const DescriptorAddress) { const uint8_t DescriptorType = (wValue >> 8); lsrs r2, r0, #8 const uint8_t DescriptorIndex = (wValue & 0xFF); const void* Address = NULL; uint16_t Size = NO_DESCRIPTOR; switch (DescriptorType) { cmp r2, #3 beq.n bhi.n cmp r2, #1 beq.n cmp r2, #2 bne.n ldr r2, [pc, #80] @ () movs r0, #59 @ 0x3b } break; } *DescriptorAddress = Address; str r2, [r3, #0] return Size; } bx lr switch (DescriptorType) { cmp r2, #33 @ 0x21 beq.n cmp r2, #34 @ 0x22 beq.n uint16_t Size = NO_DESCRIPTOR; movs r0, #0 const void* Address = NULL; mov r2, r0 b.n const uint8_t DescriptorIndex = (wValue & 0xFF); uxtb r0, r0 switch (DescriptorIndex) { cmp r0, #2 bhi.n ldr r2, [pc, #56] @ () ldr r1, [pc, #60] @ () ldr.w r2, [r2, r0, lsl #2] ldrb r0, [r1, r0] b.n switch (wIndex) { cbz r1, cmp r1, #1 bne.n ldr r2, [pc, #48] @ () movs r0, #9 b.n switch (wIndex) { cbz r1, cmp r1, #1 bne.n ldr r2, [pc, #40] @ () movs r0, #182 @ 0xb6 b.n Address = &DeviceDescriptor; ldr r2, [pc, #36] @ () Size = sizeof(USB_Descriptor_Device_t); movs r0, #18 b.n Address = &ConfigurationDescriptor.Keyboard_HID; ldr r2, [pc, #36] @ () Size = sizeof(USB_HID_Descriptor_HID_t); movs r0, #9 b.n Address = &KeyboardReport; ldr r2, [pc, #32] @ () Size = sizeof(KeyboardReport); movs r0, #68 @ 0x44 b.n nop .word 0x60008c74 .word 0x60008c08 .word 0x60008c04 .word 0x60008c9f .word 0x60008cc1 .word 0x60008caf .word 0x60008c86 .word 0x60008d77 <__core_init>: #if CH_CFG_MEMCORE_SIZE == 0 extern uint8_t __heap_base__[]; extern uint8_t __heap_end__[]; /*lint -save -e9033 [10.8] Required cast operations.*/ ch_memcore.basemem = __heap_base__; ldr r3, [pc, #8] @ (<__core_init+0xc>) ldr r2, [pc, #12] @ (<__core_init+0x10>) str r2, [r3, #0] ch_memcore.topmem = __heap_end__; ldr r2, [pc, #12] @ (<__core_init+0x14>) str r2, [r3, #4] static uint8_t static_heap[CH_CFG_MEMCORE_SIZE]; ch_memcore.basemem = &static_heap[0]; ch_memcore.topmem = &static_heap[CH_CFG_MEMCORE_SIZE]; #endif } bx lr .word 0x2000207c .word 0x200021a8 .word 0x20080000 : uint8_t *p, *next; chDbgCheckClassI(); chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.basemem + offset, align); ldr r3, [pc, #36] @ () void *chCoreAllocFromBaseI(size_t size, unsigned align, size_t offset) { push {r4, r5, lr} p = (uint8_t *)MEM_ALIGN_NEXT(ch_memcore.basemem + offset, align); ldr r4, [r3, #0] subs r5, r1, #1 add r2, r4 negs r1, r1 add r2, r5 ands r2, r1 next = p + size; /* Considering also the case where there is numeric overflow.*/ if ((next > ch_memcore.topmem) || (next < ch_memcore.basemem)) { ldr r1, [r3, #4] next = p + size; add r0, r2 if ((next > ch_memcore.topmem) || (next < ch_memcore.basemem)) { cmp r0, r1 bhi.n cmp r0, r4 bcc.n return NULL; } ch_memcore.basemem = next; str r0, [r3, #0] return p; } mov r0, r2 pop {r4, r5, pc} return NULL; movs r2, #0 b.n nop .word 0x2000207c : * @return A pointer to the allocated memory block. * @retval NULL allocation failed, core memory exhausted. * * @api */ void *chCoreAllocFromBase(size_t size, unsigned align, size_t offset) { push {r3, lr} movs r3, #48 @ 0x30 msr BASEPRI, r3 void *p; chSysLock(); p = chCoreAllocFromBaseI(size, align, offset); bl movs r3, #0 msr BASEPRI, r3 chSysUnlock(); return p; } pop {r3, pc} <__cpu_init>: */ #if !defined(__DOXYGEN__) __attribute__((weak)) #endif /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ void __cpu_init(void) { push {r4, r5, r6, lr} \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ __STATIC_FORCEINLINE void __DSB(void) { __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy __STATIC_INLINE void SCB_EnableICache (void) { #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) __DSB(); __ISB(); SCB->ICIALLU = 0UL; /* invalidate I-Cache */ ldr r2, [pc, #104] @ (<__cpu_init+0x74>) movs r1, #0 str.w r1, [r2, #592] @ 0x250 __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy __DSB(); __ISB(); SCB->CCR |= (uint32_t)SCB_CCR_IC_Msk; /* enable I-Cache */ ldr r3, [r2, #20] orr.w r3, r3, #131072 @ 0x20000 str r3, [r2, #20] __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/ /* Level 1 data cache */ str.w r1, [r2, #132] @ 0x84 __ASM volatile ("dsb 0xF":::"memory"); dsb sy __DSB(); ccsidr = SCB->CCSIDR; ldr.w r3, [r2, #128] @ 0x80 /* invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); ubfx r0, r3, #3, #10 sets = (uint32_t)(CCSIDR_SETS(ccsidr)); ubfx r3, r3, #13, #15 lsls r3, r3, #5 do { SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | movw r4, #16352 @ 0x3fe0 and.w r6, r3, r4 ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); mov r1, r0 SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | orr.w r5, r6, r1, lsl #30 ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways-- != 0U); subs r1, #1 SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | str.w r5, [r2, #608] @ 0x260 } while (ways-- != 0U); bcs.n <__cpu_init+0x4a> } while(sets-- != 0U); subs r3, #32 cmn.w r3, #32 bne.n <__cpu_init+0x44> dsb sy __DSB(); SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */ ldr r3, [r2, #20] orr.w r3, r3, #65536 @ 0x10000 str r3, [r2, #20] dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy #if CORTEX_MODEL == 7 SCB_EnableICache(); SCB_EnableDCache(); #endif } pop {r4, r5, r6, pc} .word 0xe000ed00 <__default_exit>: #endif /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ void __default_exit(void) { /*lint -restore*/ while (true) { b.n <__default_exit> ... <__init_ram_areas>: #endif /** * @brief Performs the initialization of the various RAM areas. */ void __init_ram_areas(void) { push {r4, r5, r6, lr} #if CRT0_AREAS_NUMBER > 0 const ram_init_area_t *rap = ram_areas; ldr r4, [pc, #80] @ (<__init_ram_areas+0x54>) void __init_ram_areas(void) { movs r5, #8 do { uint32_t *tp = rap->init_text_area; uint32_t *p = rap->init_area; ldr r0, [r4, #4] /* Copying initialization data.*/ while (p < rap->clear_area) { ldr r3, [r4, #0] ldr r2, [r4, #8] subs r3, #4 uint32_t *p = rap->init_area; mov r1, r0 while (p < rap->clear_area) { cmp r2, r1 bhi.n <__init_ram_areas+0x48> adds r3, r2, #3 subs r3, r3, r0 subs r1, r0, #3 bic.w r3, r3, #3 cmp r1, r2 it hi movhi r3, #0 add r0, r3 tp++; } /* Zeroing clear area.*/ while (p < rap->no_init_area) { *p = 0; ldr r3, [r4, #12] adds r2, r3, #3 subs r2, r2, r0 subs r1, r0, #3 bic.w r2, r2, #3 cmp r1, r3 it hi movhi r2, #0 movs r1, #0 bl p++; } rap++; } while (rap < &ram_areas[CRT0_AREAS_NUMBER]); subs r5, #1 rap++; add.w r4, r4, #16 while (rap < &ram_areas[CRT0_AREAS_NUMBER]); bne.n <__init_ram_areas+0x6> #endif } pop {r4, r5, r6, pc} *p = *tp; ldr.w r6, [r3, #4]! str.w r6, [r1], #4 tp++; b.n <__init_ram_areas+0x10> nop .word 0x60008dbc : * interrupts are enabled. * @post the system is in @p ch_sys_running state. * * @special */ void chSysInit(void) { push {r3, r4, r5, lr} unsigned i; /* System object initialization.*/ ch_system.state = ch_sys_initializing; ldr r4, [pc, #32] @ () movs r3, #1 for (i = 0U; i < (unsigned)PORT_CORES_NUMBER; i++) { ch_system.instances[i] = NULL; movs r5, #0 ch_system.state = ch_sys_initializing; strb r3, [r4, #0] ch_system.instances[i] = NULL; str r5, [r4, #4] * @notapi */ static inline void __oslib_init(void) { #if CH_CFG_USE_MEMCORE == TRUE __core_init(); bl <__core_init> /* OS library modules.*/ __oslib_init(); /* Initializing default OS instance.*/ chInstanceObjectInit(&ch0, &ch_core0_cfg); ldr r1, [pc, #20] @ () ldr r0, [pc, #24] @ () bl /* It is alive now.*/ ch_system.state = ch_sys_running; movs r3, #2 strb r3, [r4, #0] __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); msr BASEPRI, r5 chSysUnlock(); } pop {r3, r4, r5, pc} nop .word 0x20002088 .word 0x60008f84 .word 0x20002090 : __ASM volatile ("cpsid i" : : : "memory"); cpsid i /* Logging the event.*/ __trace_halt(reason); /* Pointing to the passed message.*/ currcore->dbg.panic_msg = reason; ldr r3, [pc, #12] @ () str r0, [r3, #92] @ 0x5c via some inter-core messaging or other means.*/ PORT_SYSTEM_HALT_HOOK(); #endif /* Entering the halted state.*/ ch_system.state = ch_sys_halted; ldr r3, [pc, #12] @ () movs r2, #3 strb r2, [r3, #0] /* Harmless infinite loop.*/ while (true) { b.n nop .word 0x20002090 .word 0x20002088 : * * @xclass */ static inline thread_t *chThdGetSelfX(void) { return __sch_get_currthread(); ldr r3, [pc, #12] @ () ldr r2, [r3, #12] chDbgCheckClassI(); #if CH_CFG_TIME_QUANTUM > 0 /* Running thread has not used up quantum yet? */ if (currtp->ticks > (tslices_t)0) { ldrb r3, [r2, #22] cbz r3, /* Decrement remaining quantum.*/ currtp->ticks--; subs r3, #1 strb r3, [r2, #22] } #endif #if CH_DBG_THREADS_PROFILING == TRUE currtp->time++; #endif chVTDoTickI(); b.w .word 0x20002090 : * @param[in] dlep element to be inserted before the header element * @param[in] delta delta of the element to be inserted * * @notapi */ static inline void ch_dlist_insert(ch_delta_list_t *dlhp, push {r4, lr} sysinterval_t delta) { ch_delta_list_t *dlp; /* The delta list is scanned in order to find the correct position for this element. */ dlp = dlhp->next; ldr r4, [pc, #40] @ () ldr r3, [r4, #16] while (likely(dlp->delta < delta)) { ldr r2, [r3, #8] cmp r1, r2 bhi.n dlp->prev = dlp->next->prev; ldr r2, [r3, #4] dlp->delta = delta; str r1, [r0, #8] dlp->next = dlhp; str r3, [r0, #0] dlp->prev = dlp->next->prev; str r2, [r0, #4] dlp->prev->next = dlp; str r0, [r2, #0] /* The timer is inserted in the delta list.*/ ch_dlist_insert_before(dlp, dlep, delta); /* Adjusting delta for the following element.*/ dlp->delta -= delta; ldr r2, [r3, #8] dlhp->prev = dlp; str r0, [r3, #4] dlp->delta -= delta; subs r2, r2, r1 str r2, [r3, #8] /* Special case when the inserted element is in last position in the list, the value in the header must be restored, just doing it is faster than checking then doing.*/ dlhp->delta = (sysinterval_t)-1; mov.w r3, #4294967295 @ 0xffffffff str r3, [r4, #24] } pop {r4, pc} dlp = dlp->next; ldr r3, [r3, #0] delta -= dlp->delta; subs r1, r1, r2 dlp = dlp->next; b.n .word 0x20002090 : * function * * @iclass */ void chVTDoSetI(virtual_timer_t *vtp, sysinterval_t delay, vtfunc_t vtfunc, void *par) { push {r4} chDbgCheckClassI(); chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (delay != TIME_IMMEDIATE)); /* Timer initialization.*/ vtp->par = par; str r3, [r0, #16] vtp->func = vtfunc; vtp->reload = (sysinterval_t)0; movs r3, #0 /* Inserting the timer in the delta list.*/ vt_enqueue(vtlp, vtp, delay); } pop {r4} vtp->func = vtfunc; str r2, [r0, #12] vtp->reload = (sysinterval_t)0; str r3, [r0, #20] ch_dlist_insert(&vtlp->dlist, &vtp->dlist, delta); b.w : chDbgAssert(chVTIsArmedI(vtp), "timer not armed"); #if CH_CFG_ST_TIMEDELTA == 0 /* The delta of the timer is added to the next timer.*/ vtp->dlist.next->delta += vtp->dlist.delta; ldr r3, [r0, #0] ldr r1, [r0, #8] ldr r2, [r3, #8] add r2, r1 str r2, [r3, #8] * * @notapi */ static inline ch_delta_list_t *ch_dlist_dequeue(ch_delta_list_t *dlp) { dlp->prev->next = dlp->next; ldr r2, [r0, #4] str r3, [r2, #0] dlp->next->prev = dlp->prev; str r2, [r3, #4] /* Removing the element from the delta list, marking it as not armed.*/ (void) ch_dlist_dequeue(&vtp->dlist); vtp->dlist.next = NULL; movs r3, #0 str r3, [r0, #0] /* The above code changes the value in the header when the removed element is the last of the list, restoring it.*/ vtlp->dlist.delta = (sysinterval_t)-1; ldr r3, [pc, #8] @ () mov.w r2, #4294967295 @ 0xffffffff str r2, [r3, #24] delta = vtlp->dlist.next->delta - nowdelta; /* Setting up the alarm.*/ vt_set_alarm(now, delta); #endif /* CH_CFG_ST_TIMEDELTA > 0 */ } bx lr nop .word 0x20002090 : * to acquire the lock if needed. This is done in order to reduce * interrupts jitter when many timers are in use. * * @iclass */ void chVTDoTickI(void) { push {r4, r5, r6, lr} virtual_timers_list_t *vtlp = &currcore->vtlist; chDbgCheckClassI(); #if CH_CFG_ST_TIMEDELTA == 0 vtlp->systime++; ldr r5, [pc, #72] @ () ldr r3, [r5, #28] return (bool)(dlhp != dlhp->next); mov r2, r5 adds r3, #1 str r3, [r5, #28] ldr.w r3, [r2, #16]! if (ch_dlist_notempty(&vtlp->dlist)) { cmp r3, r2 beq.n /* The list is not empty, processing elements on top.*/ --vtlp->dlist.next->delta; ldr r2, [r3, #8] subs r2, #1 str r2, [r3, #8] __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); movs r6, #48 @ 0x30 while (vtlp->dlist.next->delta == (sysinterval_t)0) { ldr r4, [r5, #16] ldr r3, [r4, #8] cbz r3, vtp->dlist.delta -= nowdelta; /* Update alarm time to next timer.*/ vt_set_alarm(now, vtp->dlist.delta); #endif /* CH_CFG_ST_TIMEDELTA > 0 */ } pop {r4, r5, r6, pc} dlp->prev->next = dlp->next; ldr r2, [r4, #0] ldr r1, [r4, #4] str r2, [r1, #0] dlp->next->prev = dlp->prev; str r1, [r2, #4] vtp->dlist.next = NULL; str r3, [r4, #0] msr BASEPRI, r3 vtp->func(vtp, vtp->par); ldr r3, [r4, #12] ldr r1, [r4, #16] mov r0, r4 blx r3 msr BASEPRI, r6 if (vtp->reload > (sysinterval_t)0) { ldr r1, [r4, #20] cmp r1, #0 beq.n ch_dlist_insert(&vtlp->dlist, &vtp->dlist, vtp->reload); mov r0, r4 bl b.n .word 0x20002090 <__sch_ready_behind>: /* Tracing the event.*/ __trace_ready(tp, tp->u.rdymsg); /* The thread is marked ready.*/ tp->state = CH_STATE_READY; movs r3, #0 strb r3, [r0, #20] } while (unlikely(pqp->prio >= p->prio)); ldr r2, [r0, #8] /* Insertion in the priority queue.*/ return threadref(ch_pqueue_insert_behind(&tp->owner->rlist.pqueue, ldr r3, [r0, #16] pqp = pqp->next; ldr r3, [r3, #0] } while (unlikely(pqp->prio >= p->prio)); ldr r1, [r3, #8] cmp r1, r2 bcs.n <__sch_ready_behind+0x8> p->prev = pqp->prev; ldr r2, [r3, #4] p->next = pqp; str r3, [r0, #0] p->prev = pqp->prev; str r2, [r0, #4] p->prev->next = p; str r0, [r2, #0] pqp->prev = p; str r0, [r3, #4] &tp->hdr.pqueue)); } bx lr <__sch_ready_ahead>: /* Tracing the event.*/ __trace_ready(tp, tp->u.rdymsg); /* The thread is marked ready.*/ tp->state = CH_STATE_READY; movs r3, #0 strb r3, [r0, #20] } while (unlikely(pqp->prio > p->prio)); ldr r2, [r0, #8] /* Insertion in the priority queue.*/ return threadref(ch_pqueue_insert_ahead(&tp->owner->rlist.pqueue, ldr r3, [r0, #16] pqp = pqp->next; ldr r3, [r3, #0] } while (unlikely(pqp->prio > p->prio)); ldr r1, [r3, #8] cmp r1, r2 bhi.n <__sch_ready_ahead+0x8> p->prev = pqp->prev; ldr r2, [r3, #4] p->next = pqp; str r3, [r0, #0] p->prev = pqp->prev; str r2, [r0, #4] p->prev->next = p; str r0, [r2, #0] pqp->prev = p; str r0, [r3, #4] &tp->hdr.pqueue)); } bx lr <__sch_reschedule_ahead>: * * @notapi */ static void __sch_reschedule_ahead(void) { os_instance_t *oip = currcore; thread_t *otp = __instance_get_currthread(oip); ldr r3, [pc, #32] @ (<__sch_reschedule_ahead+0x24>) static void __sch_reschedule_ahead(void) { push {r4, lr} ch_priority_queue_t *p = pqp->next; ldr r4, [r3, #0] thread_t *otp = __instance_get_currthread(oip); ldr r0, [r3, #12] pqp->next = p->next; ldr r2, [r4, #0] str r2, [r3, #0] pqp->next->prev = pqp; str r3, [r2, #4] thread_t *ntp; /* Picks the first thread from the ready queue and makes it current.*/ ntp = threadref(ch_pqueue_remove_highest(&oip->rlist.pqueue)); ntp->state = CH_STATE_CURRENT; movs r2, #1 strb r2, [r4, #20] __instance_set_currthread(oip, ntp); str r4, [r3, #12] if (otp->hdr.pqueue.prio == IDLEPRIO) { CH_CFG_IDLE_LEAVE_HOOK(); } /* Placing in ready list ahead of peers.*/ otp = __sch_ready_ahead(otp); bl <__sch_ready_ahead> mov r1, r0 /* Swap operation as tail call.*/ chSysSwitch(ntp, otp); mov r0, r4 } ldmia.w sp!, {r4, lr} chSysSwitch(ntp, otp); b.w <__port_switch> .word 0x20002090 <__sch_wakeup>: /* * Timeout wakeup callback. */ static void __sch_wakeup(virtual_timer_t *vtp, void *p) { push {r3, lr} mov r0, r1 movs r3, #48 @ 0x30 msr BASEPRI, r3 thread_t *tp = threadref(p); (void)vtp; chSysLockFromISR(); switch (tp->state) { ldrb r2, [r1, #20] movs r3, #0 cmp r2, #5 bhi.n <__sch_wakeup+0x20> tbb [pc, r2] .short 0x050b .word 0x0e120305 /* Handling the special case where the thread has been made ready by another thread with higher priority.*/ chSysUnlockFromISR(); return; case CH_STATE_SUSPENDED: *tp->u.wttrp = NULL; ldr r2, [r0, #24] str r3, [r2, #0] /* Any other state, nothing to do.*/ break; } /* Standard message for timeout conditions.*/ tp->u.rdymsg = MSG_TIMEOUT; mov.w r3, #4294967295 @ 0xffffffff str r3, [r0, #24] /* Goes behind peers because it went to sleep voluntarily.*/ (void) __sch_ready_behind(tp); bl <__sch_ready_behind> movs r3, #0 msr BASEPRI, r3 chSysUnlockFromISR(); return; } pop {r3, pc} chSemFastSignalI(tp->u.wtsemp); ldr r2, [r0, #24] */ static inline void chSemFastSignalI(semaphore_t *sp) { chDbgCheckClassI(); sp->cnt++; ldr r3, [r2, #8] adds r3, #1 str r3, [r2, #8] p->prev->next = p->next; ldr r2, [r0, #4] ldr r3, [r0, #0] str r3, [r2, #0] p->next->prev = p->prev; str r2, [r3, #4] return p; b.n <__sch_wakeup+0x20> : the other core.*/ chSysNotifyInstance(tp->owner); } #endif return __sch_ready_behind(tp); b.w <__sch_ready_behind> : * * @sclass */ void chSchGoSleepS(tstate_t newstate) { os_instance_t *oip = currcore; thread_t *otp = __instance_get_currthread(oip); ldr r3, [pc, #24] @ () ldr r1, [r3, #12] otp->state = newstate; #if CH_CFG_TIME_QUANTUM > 0 /* The thread is renouncing its remaining time slices so it will have a new time quantum when it will wakeup.*/ otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; movs r2, #20 otp->state = newstate; strb r0, [r1, #20] ch_priority_queue_t *p = pqp->next; ldr r0, [r3, #0] otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; strb r2, [r1, #22] pqp->next = p->next; ldr r2, [r0, #0] str r2, [r3, #0] pqp->next->prev = pqp; str r3, [r2, #4] #endif /* Next thread in ready list becomes current.*/ ntp = threadref(ch_pqueue_remove_highest(&oip->rlist.pqueue)); ntp->state = CH_STATE_CURRENT; movs r2, #1 strb r2, [r0, #20] __instance_set_currthread(oip, ntp); str r0, [r3, #12] if (ntp->hdr.pqueue.prio == IDLEPRIO) { CH_CFG_IDLE_ENTER_HOOK(); } /* Swap operation as tail call.*/ chSysSwitch(ntp, otp); b.w <__port_switch> .word 0x20002090 : * @return The wakeup message. * @retval MSG_TIMEOUT if a timeout occurs. * * @sclass */ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) { push {r4, r5, lr} thread_t *tp = __instance_get_currthread(currcore); ldr r3, [pc, #48] @ () ldr r5, [r3, #12] chDbgCheckClassS(); if (TIME_INFINITE != timeout) { adds r3, r1, #1 msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) { sub sp, #28 mov r4, r0 if (TIME_INFINITE != timeout) { beq.n virtual_timer_t vt; chVTDoSetI(&vt, timeout, __sch_wakeup, (void *)tp); mov r3, r5 ldr r2, [pc, #36] @ () mov r0, sp bl chSchGoSleepS(newstate); mov r0, r4 bl if (chVTIsArmedI(&vt)) { ldr r3, [sp, #0] cbz r3, chVTDoResetI(&vt); mov r0, sp bl else { chSchGoSleepS(newstate); } return tp->u.rdymsg; } ldr r0, [r5, #24] add sp, #28 pop {r4, r5, pc} chSchGoSleepS(newstate); bl b.n .word 0x20002090 .word 0x60005159 : chDbgCheckClassS(); /* Note, we are favoring the path where the reschedule is necessary because higher priority threads are ready.*/ if (likely(firstprio(&oip->rlist.pqueue) > tp->hdr.pqueue.prio)) { ldr r3, [pc, #16] @ () ldr r2, [r3, #0] ldr r3, [r3, #12] ldr r2, [r2, #8] ldr r3, [r3, #8] cmp r2, r3 bls.n __sch_reschedule_ahead(); b.w <__sch_reschedule_ahead> } } bx lr .word 0x20002090 : * * @special */ bool chSchIsPreemptionRequired(void) { os_instance_t *oip = currcore; thread_t *tp = __instance_get_currthread(oip); ldr r3, [pc, #32] @ () ldr r2, [r3, #12] tprio_t p1 = firstprio(&oip->rlist.pqueue); ldr r3, [r3, #0] ldr r0, [r3, #8] tprio_t p2 = tp->hdr.pqueue.prio; ldr r3, [r2, #8] #if CH_CFG_TIME_QUANTUM > 0 /* If the running thread has not reached its time quantum, reschedule only if the first thread on the ready queue has a higher priority. Otherwise, if the running thread has used up its time quantum, reschedule if the first thread on the ready queue has equal or higher priority.*/ return (tp->ticks > (tslices_t)0) ? (p1 > p2) : (p1 >= p2); ldrb r2, [r2, #22] cbz r2, cmp r0, r3 ite ls movls r0, #0 movhi r0, #1 bx lr cmp r0, r3 ite cc movcc r0, #0 movcs r0, #1 #else /* If the round robin preemption feature is not enabled then performs a simpler comparison.*/ return p1 > p2; #endif } bx lr nop .word 0x20002090 : * * @special */ void chSchDoPreemption(void) { os_instance_t *oip = currcore; thread_t *otp = __instance_get_currthread(oip); ldr r3, [pc, #48] @ () void chSchDoPreemption(void) { push {r4, lr} ch_priority_queue_t *p = pqp->next; ldr r4, [r3, #0] thread_t *otp = __instance_get_currthread(oip); ldr r0, [r3, #12] pqp->next = p->next; ldr r2, [r4, #0] str r2, [r3, #0] pqp->next->prev = pqp; str r3, [r2, #4] thread_t *ntp; /* Picks the first thread from the ready queue and makes it current.*/ ntp = threadref(ch_pqueue_remove_highest(&oip->rlist.pqueue)); ntp->state = CH_STATE_CURRENT; movs r2, #1 strb r2, [r4, #20] __instance_set_currthread(oip, ntp); str r4, [r3, #12] } #if CH_CFG_TIME_QUANTUM > 0 /* If CH_CFG_TIME_QUANTUM is enabled then there are two different scenarios to handle on preemption: time quantum elapsed or not.*/ if (otp->ticks == (tslices_t)0) { ldrb r3, [r0, #22] cbnz r3, /* The thread consumed its time quantum so it is enqueued behind threads with same priority level, however, it acquires a new time quantum.*/ otp = __sch_ready_behind(otp); bl <__sch_ready_behind> /* The thread being swapped out receives a new time quantum.*/ otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; movs r3, #20 otp = __sch_ready_behind(otp); mov r1, r0 otp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; strb r3, [r0, #22] ahead of its peers.*/ otp = __sch_ready_ahead(otp); #endif /* !(CH_CFG_TIME_QUANTUM > 0) */ /* Swap operation as tail call.*/ chSysSwitch(ntp, otp); mov r0, r4 } ldmia.w sp!, {r4, lr} chSysSwitch(ntp, otp); b.w <__port_switch> otp = __sch_ready_ahead(otp); bl <__sch_ready_ahead> mov r1, r0 b.n .word 0x20002090 <__idle_thread>: * @note Implemented as an inlined @p WFI instruction. */ __STATIC_FORCEINLINE void port_wait_for_interrupt(void) { #if CORTEX_ENABLE_WFI_IDLE == TRUE __WFI(); wfi */ static void __idle_thread(void *p) { (void)p; while (true) { b.n <__idle_thread> : * @param[in] oicp pointer to the @p os_instance_config_t structure * * @special */ void chInstanceObjectInit(os_instance_t *oip, const os_instance_config_t *oicp) { push {r4, r5, r6, lr} core_id = port_get_core_id(); #else core_id = 0U; #endif chDbgAssert(ch_system.instances[core_id] == NULL, "instance already registered"); ch_system.instances[core_id] = oip; ldr r3, [pc, #108] @ () /* Core associated to this instance.*/ oip->core_id = core_id; /* Keeping a reference to the configuration data.*/ oip->config = oicp; str r1, [r0, #48] @ 0x30 oip->core_id = core_id; movs r5, #0 const os_instance_config_t *oicp) { mov r4, r0 sub sp, #24 oip->core_id = core_id; str r5, [r0, #40] @ 0x28 const os_instance_config_t *oicp) { mov r6, r1 ch_system.instances[core_id] = oip; str r0, [r3, #4] /* Port initialization for the current instance.*/ port_init(oip); bl * * @notapi */ static inline void __vt_object_init(virtual_timers_list_t *vtlp) { ch_dlist_init(&vtlp->dlist); add.w r3, r4, #16 dlhp->next = dlhp; str r3, [r4, #16] dlhp->prev = dlhp; str r3, [r4, #20] dlhp->delta = (sysinterval_t)-1; mov.w r3, #4294967295 @ 0xffffffff str r3, [r4, #24] return currcore->vtlist.systime; ldr r3, [pc, #76] @ () #if CH_CFG_ST_TIMEDELTA == 0 vtlp->systime = (systime_t)0; str r5, [r4, #28] return currcore->vtlist.systime; ldr r1, [r3, #28] pqp->next = pqp; str r4, [r4, #0] #else /* CH_CFG_ST_TIMEDELTA > 0 */ vtlp->lasttime = (systime_t)0; #endif /* CH_CFG_ST_TIMEDELTA > 0 */ #if CH_CFG_USE_TIMESTAMP == TRUE vtlp->laststamp = (systimestamp_t)chVTGetSystemTimeX(); mov r2, r1 mov r3, r5 strd r2, r3, [r4, #32] /* Now this instructions flow becomes the main thread.*/ #if CH_CFG_USE_REGISTRY == TRUE oip->rlist.current = __thd_object_init(oip, &oip->mainthread, (const char *)&ch_debug, NORMALPRIO); #else oip->rlist.current = __thd_object_init(oip, &oip->mainthread, add.w r1, r4, #52 @ 0x34 ldr r2, [pc, #60] @ () pqp->prev = pqp; str r4, [r4, #4] pqp->prio = (tprio_t)0; str r5, [r4, #8] * * @notapi */ static inline void __rfcu_object_init(rfcu_t *rfcup) { rfcup->mask = (rfcu_mask_t)0; str r5, [r4, #44] @ 0x2c * * @notapi */ static inline void __dbg_object_init(system_debug_t *sdp) { sdp->panic_msg = NULL; str r5, [r4, #92] @ 0x5c movs r3, #128 @ 0x80 mov r0, r4 bl <__thd_object_init> #if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || (CH_CFG_USE_DYNAMIC == TRUE) oip->rlist.current->wabase = oicp->mainthread_base; #endif /* Setting up the caller as current thread.*/ oip->rlist.current->state = CH_STATE_CURRENT; movs r3, #1 oip->rlist.current = __thd_object_init(oip, &oip->mainthread, str r0, [r4, #12] /* User instance initialization hook.*/ CH_CFG_OS_INSTANCE_INIT_HOOK(oip); #if CH_CFG_NO_IDLE_THREAD == FALSE { thread_descriptor_t idle_descriptor = { ldr r2, [pc, #44] @ () oip->rlist.current->state = CH_STATE_CURRENT; strb r3, [r0, #20] thread_descriptor_t idle_descriptor = { str r2, [sp, #0] ldr r2, [r6, #4] str r2, [sp, #4] ldr r2, [r6, #8] strd r2, r3, [sp, #8] ldr r3, [pc, #32] @ () #endif /* This thread has the lowest priority in the system, its role is just to serve interrupts in its context while keeping the lowest energy saving mode compatible with the system status.*/ (void) chThdCreateI(&idle_descriptor); mov r0, sp thread_descriptor_t idle_descriptor = { strd r3, r5, [sp, #16] (void) chThdCreateI(&idle_descriptor); bl } #endif } add sp, #24 pop {r4, r5, r6, pc} nop .word 0x20002088 .word 0x20002090 .word 0x60008e3f .word 0x60008e44 .word 0x60005275 <__thd_object_init>: thread_t *tp, const char *name, tprio_t prio) { tp->hdr.pqueue.prio = prio; tp->state = CH_STATE_WTSTART; movs r2, #2 tp->hdr.pqueue.prio = prio; str r3, [r1, #8] tp->state = CH_STATE_WTSTART; strh r2, [r1, #20] tp->owner = oip; #if CH_CFG_TIME_QUANTUM > 0 tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; #endif #if CH_CFG_USE_MUTEXES == TRUE tp->realprio = prio; str r3, [r1, #36] @ 0x24 tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; movs r2, #20 tp->mtxlist = NULL; movs r3, #0 tp->owner = oip; str r0, [r1, #16] tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; strb r2, [r1, #22] tp->mtxlist = NULL; str r3, [r1, #32] #endif #if CH_CFG_USE_EVENTS == TRUE tp->epending = (eventmask_t)0; str r3, [r1, #28] #if CH_DBG_STATISTICS == TRUE chTMObjectInit(&tp->stats); #endif CH_CFG_THREAD_INIT_HOOK(tp); return tp; } mov r0, r1 bx lr : chDbgCheck((tdp->prio <= HIGHPRIO) && (tdp->funcp != NULL)); /* The thread structure is laid out in the upper part of the thread workspace. The thread position structure is aligned to the required stack alignment because it represents the stack top.*/ tp = threadref(((uint8_t *)tdp->wend - ldr r3, [r0, #8] if (tdp->instance != NULL) { return __thd_object_init(tdp->instance, tp, tdp->name, tdp->prio); } #endif return __thd_object_init(currcore, tp, tdp->name, tdp->prio); ldr r1, [r0, #12] PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg); sub.w r2, r3, #76 @ 0x4c str.w r2, [r3, #-28] ldr r2, [r0, #16] str.w r2, [r3, #-76] ldr r2, [r0, #20] str.w r2, [r3, #-72] ldr r2, [pc, #48] @ () tp->owner = oip; ldr r0, [pc, #52] @ () PORT_SETUP_CONTEXT(tp, tdp->wbase, tp, tdp->funcp, tdp->arg); str.w r2, [r3, #-44] tp->state = CH_STATE_WTSTART; movs r2, #2 strb.w r2, [r3, #-20] tp->owner = oip; str.w r0, [r3, #-24] tp->flags = CH_FLAG_MODE_STATIC; movs r2, #0 tp->ticks = (tslices_t)CH_CFG_TIME_QUANTUM; movs r0, #20 strb.w r0, [r3, #-18] tp->hdr.pqueue.prio = prio; str.w r1, [r3, #-32] tp->flags = CH_FLAG_MODE_STATIC; strb.w r2, [r3, #-19] tp->realprio = prio; str.w r1, [r3, #-4] tp->mtxlist = NULL; str.w r2, [r3, #-8] tp->epending = (eventmask_t)0; str.w r2, [r3, #-12] } sub.w r0, r3, #40 @ 0x28 bx lr .word 0x60001901 .word 0x20002090 : * @return The pointer to the @p thread_t structure allocated for * the thread into the working space area. * * @iclass */ thread_t *chThdCreateI(const thread_descriptor_t *tdp) { push {r3, lr} return chSchReadyI(chThdCreateSuspendedI(tdp)); bl } ldmia.w sp!, {r3, lr} return chSchReadyI(chThdCreateSuspendedI(tdp)); b.w ... : ldr r3, [pc, #8] @ () */ void chThdExitS(msg_t msg) { thread_t *currtp = chThdGetSelfX(); /* Storing exit message.*/ currtp->u.exitcode = msg; ldr r3, [r3, #12] str r0, [r3, #24] #endif } #endif /* Going into final state.*/ chSchGoSleepS(CH_STATE_FINAL); movs r0, #15 b.w .word 0x20002090 : movs r3, #48 @ 0x30 msr BASEPRI, r3 chThdExitS(msg); b.w : * - @a TIME_IMMEDIATE this value is not allowed. * . * * @api */ void chThdSleep(sysinterval_t time) { push {r3, lr} mov r1, r0 movs r3, #48 @ 0x30 msr BASEPRI, r3 */ static inline void chThdSleepS(sysinterval_t ticks) { chDbgCheck(ticks != TIME_IMMEDIATE); (void) chSchGoSleepTimeoutS(CH_STATE_SLEEPING, ticks); movs r0, #8 bl movs r3, #0 msr BASEPRI, r3 chSysLock(); chThdSleepS(time); chSysUnlock(); } pop {r3, pc} ... : return __sch_get_currthread(); ldr r3, [pc, #20] @ () ldr r3, [r3, #12] msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) { thread_t *tp = chThdGetSelfX(); chDbgAssert(*trp == NULL, "not NULL"); if (unlikely(TIME_IMMEDIATE == timeout)) { cbz r1, return MSG_TIMEOUT; } *trp = tp; str r3, [r0, #0] tp->u.wttrp = trp; str r0, [r3, #24] return chSchGoSleepTimeoutS(CH_STATE_SUSPENDED, timeout); movs r0, #3 b.w } mov.w r0, #4294967295 @ 0xffffffff bx lr nop .word 0x20002090 : * @param[in] trp a pointer to a thread reference object * @param[in] msg the message code * * @iclass */ void chThdResumeI(thread_reference_t *trp, msg_t msg) { mov r3, r0 if (*trp != NULL) { ldr r0, [r0, #0] cbz r0, thread_t *tp = *trp; chDbgAssert(tp->state == CH_STATE_SUSPENDED, "not CH_STATE_SUSPENDED"); *trp = NULL; movs r2, #0 str r2, [r3, #0] tp->u.rdymsg = msg; str r1, [r0, #24] (void) chSchReadyI(tp); b.w } } bx lr : __ASM volatile ("MRS %0, psp" : "=r" (result) ); mrs r3, PSP /* From privileged mode, it is used for context discarding in the preemption code.*/ /* Unstacking procedure, discarding the current exception context and positioning the stack to point to the real one.*/ psp += sizeof (struct port_extctx); adds r3, #32 __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); msr PSP, r3 __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); movs r3, #0 msr BASEPRI, r3 #endif /* Restoring the normal interrupts status.*/ port_unlock_from_isr(); } } bx lr : movs r0, #48 @ 0x30 msr BASEPRI, r0 __ASM volatile ("cpsie i" : : : "memory"); cpsie i reg_value = SCB->AIRCR; /* read old register configuration */ ldr r3, [pc, #52] @ () reg_value = (reg_value | ldr r2, [pc, #56] @ () reg_value = SCB->AIRCR; /* read old register configuration */ ldr r1, [r3, #12] reg_value &= ~((uint32_t)(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk)); /* clear bits to change */ bic.w r1, r1, #1792 @ 0x700 lsls r1, r1, #16 lsrs r1, r1, #16 reg_value = (reg_value | orrs r2, r1 SCB->AIRCR = reg_value; str r2, [r3, #12] /* Initializing priority grouping.*/ NVIC_SetPriorityGrouping(CORTEX_PRIGROUP_INIT); /* DWT cycle counter enable, note, the M7 requires DWT unlocking.*/ CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; ldr.w r2, [r3, #252] @ 0xfc #if CORTEX_MODEL == 7 DWT->LAR = 0xC5ACCE55U; ldr r1, [pc, #40] @ () CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; orr.w r2, r2, #16777216 @ 0x1000000 str.w r2, [r3, #252] @ 0xfc DWT->LAR = 0xC5ACCE55U; ldr r2, [pc, #32] @ () str.w r1, [r2, #4016] @ 0xfb0 #endif DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; ldr r1, [r2, #0] orr.w r1, r1, #1 str r1, [r2, #0] SCB->SHPR[(((uint32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL); movs r2, #32 strb r2, [r3, #31] strb.w r0, [r3, #34] @ 0x22 #if (PORT_ENABLE_GUARD_PAGES == TRUE) || (PORT_USE_SYSCALL == TRUE) /* MPU is enabled.*/ mpuEnable(MPU_CTRL_PRIVDEFENA); #endif } bx lr .word 0xe000ed00 .word 0x05fa0300 .word 0xc5acce55 .word 0xe0001000 <__port_irq_epilogue>: #endif /** * @brief Exception exit redirection to @p __port_switch_from_isr(). */ void __port_irq_epilogue(void) { push {r4, lr} __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); movs r3, #48 @ 0x30 msr BASEPRI, r3 port_lock_from_isr(); if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U) { ldr r3, [pc, #44] @ (<__port_irq_epilogue+0x38>) ldr r3, [r3, #4] ands.w r3, r3, #2048 @ 0x800 beq.n <__port_irq_epilogue+0x32> __ASM volatile ("MRS %0, psp" : "=r" (result) ); mrs r4, PSP s_psp = __get_PSP(); #endif /* Adding an artificial exception return context, there is no need to populate it fully.*/ s_psp -= sizeof (struct port_extctx); subs r4, #32 /* The port_extctx structure is pointed by the S-PSP register.*/ ectxp = (struct port_extctx *)s_psp; /* Setting up a fake XPSR register value.*/ ectxp->xpsr = 0x01000000U; mov.w r3, #16777216 @ 0x1000000 str r3, [r4, #28] __ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) : ); msr PSP, r4 /* Writing back the modified S-PSP value.*/ __set_PSP(s_psp); /* The exit sequence is different depending on if a preemption is required or not.*/ if (chSchIsPreemptionRequired()) { bl cbz r0, <__port_irq_epilogue+0x2e> /* Preemption is required we need to enforce a context switch.*/ ectxp->pc = (uint32_t)__port_switch_from_isr; ldr r3, [pc, #16] @ (<__port_irq_epilogue+0x3c>) } else { /* Preemption not required, we just need to exit the exception atomically.*/ ectxp->pc = (uint32_t)__port_exit_from_isr; str r3, [r4, #24] /* Note, returning without unlocking is intentional, this is done in order to keep the rest of the context switch atomic.*/ return; } port_unlock_from_isr(); } pop {r4, pc} ectxp->pc = (uint32_t)__port_exit_from_isr; ldr r3, [pc, #16] @ (<__port_irq_epilogue+0x40>) b.n <__port_irq_epilogue+0x2a> __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); msr BASEPRI, r3 } b.n <__port_irq_epilogue+0x2c> .word 0xe000ed00 .word 0x60001913 .word 0x60001916 : * board-specific initialization is performed by invoking * @p boardInit() (usually defined in @p board.c). * * @init */ void halInit(void) { push {r3, lr} /* Initializes the OS Abstraction Layer.*/ osalInit(); /* Platform low level initializations.*/ hal_lld_init(); bl #if (HAL_USE_PAL == TRUE) || defined(__DOXYGEN__) #if defined(PAL_NEW_INIT) palInit(); #else palInit(&pal_default_config); ldr r0, [pc, #20] @ () bl <_pal_lld_init> #endif #if (HAL_USE_UART == TRUE) || defined(__DOXYGEN__) uartInit(); #endif #if (HAL_USE_USB == TRUE) || defined(__DOXYGEN__) usbInit(); bl halCommunityInit(); #endif #endif /* Board specific initialization.*/ boardInit(); bl * configured to require it. */ #if OSAL_ST_MODE != OSAL_ST_MODE_NONE stInit(); #endif } ldmia.w sp!, {r3, lr} stInit(); b.w .word 0x60008f96 : for (i = 0U; i < (unsigned)ST_LLD_NUM_ALARMS; i++) { st_callbacks[i] = NULL; } #endif st_lld_init(); b.w : * * @init */ void usbInit(void) { usb_lld_init(); b.w : * * @param[out] usbp pointer to the @p USBDriver object * * @init */ void usbObjectInit(USBDriver *usbp) { push {r4, lr} unsigned i; usbp->state = USB_STOP; movs r3, #1 void usbObjectInit(USBDriver *usbp) { mov r4, r0 usbp->config = NULL; for (i = 0; i < (unsigned)USB_MAX_ENDPOINTS; i++) { usbp->in_params[i] = NULL; movs r2, #56 @ 0x38 usbp->state = USB_STOP; strb.w r3, [r0], #44 usbp->in_params[i] = NULL; movs r1, #0 bl usbp->config = NULL; movs r3, #0 str r3, [r4, #4] usbp->out_params[i] = NULL; } usbp->transmitting = 0; str r3, [r4, #8] usbp->receiving = 0; } pop {r4, pc} : * @param[in] config pointer to the @p USBConfig object * @return The operation status. * * @api */ msg_t usbStart(USBDriver *usbp, const USBConfig *config) { push {r4, lr} movs r3, #48 @ 0x30 mov r4, r0 msr BASEPRI, r3 osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY), "invalid state"); usbp->config = config; for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { usbp->epc[i] = NULL; movs r2, #32 usbp->config = config; str r1, [r0, #4] usbp->epc[i] = NULL; movs r1, #0 adds r0, #12 bl } #if defined(USB_LLD_ENHANCED_API) msg = usb_lld_start(usbp); #else usb_lld_start(usbp); mov r0, r4 bl msg = HAL_RET_SUCCESS; #endif if (msg == HAL_RET_SUCCESS) { usbp->state = USB_READY; movs r3, #2 strb r3, [r4, #0] movs r0, #0 msr BASEPRI, r0 } osalSysUnlock(); return msg; } pop {r4, pc} : * * @param[in] usbp pointer to the @p USBDriver object * * @api */ void usbStop(USBDriver *usbp) { push {r3, r4, r5, r6, r7, lr} mov r4, r0 movs r3, #48 @ 0x30 msr BASEPRI, r3 (usbp->state == USB_SUSPENDED), "invalid state"); usb_lld_stop(usbp); usbp->config = NULL; usbp->state = USB_STOP; mov r5, r4 usb_lld_stop(usbp); bl usbp->config = NULL; movs r6, #0 usbp->state = USB_STOP; movs r3, #1 usbp->config = NULL; str r6, [r4, #4] usbp->state = USB_STOP; strb.w r3, [r5], #8 /* Resetting all ongoing synchronous operations.*/ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { adds r4, #40 @ 0x28 if (usbp->epc[i]->out_state != NULL) { osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); } } #endif usbp->epc[i] = NULL; mov r7, r6 if (usbp->epc[i] != NULL) { ldr.w r3, [r5, #4]! cbz r3, if (usbp->epc[i]->in_state != NULL) { ldr r0, [r3, #20] cbz r0, * * @iclass */ static inline void osalThreadResumeI(thread_reference_t *trp, msg_t msg) { chThdResumeI(trp, msg); mvn.w r1, #1 adds r0, #12 bl if (usbp->epc[i]->out_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #24] cbz r0, mvn.w r1, #1 adds r0, #12 bl for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { cmp r5, r4 usbp->epc[i] = NULL; str r6, [r5, #0] for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { bne.n chSchRescheduleS(); bl msr BASEPRI, r7 } osalOsRescheduleS(); osalSysUnlock(); } pop {r3, r4, r5, r6, r7, pc} : * @param[in] epcp the endpoint configuration * * @iclass */ void usbInitEndpointI(USBDriver *usbp, usbep_t ep, const USBEndpointConfig *epcp) { push {r4, r5, r6, lr} osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state"); osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); /* Logically enabling the endpoint in the USBDriver structure.*/ usbp->epc[ep] = epcp; add.w r3, r0, r1, lsl #2 const USBEndpointConfig *epcp) { mov r5, r0 /* Clearing the state structures, custom fields as well.*/ if (epcp->in_state != NULL) { ldr r0, [r2, #20] usbp->epc[ep] = epcp; str r2, [r3, #12] const USBEndpointConfig *epcp) { mov r6, r1 mov r4, r2 if (epcp->in_state != NULL) { cbz r0, memset(epcp->in_state, 0, sizeof(USBInEndpointState)); movs r2, #16 movs r1, #0 bl } if (epcp->out_state != NULL) { ldr r0, [r4, #24] cbz r0, memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); movs r2, #16 movs r1, #0 bl } /* Low level endpoint activation.*/ usb_lld_init_endpoint(usbp, ep); mov r1, r6 mov r0, r5 } ldmia.w sp!, {r4, r5, r6, lr} usb_lld_init_endpoint(usbp, ep); b.w : * * @param[in] usbp pointer to the @p USBDriver object * * @iclass */ void usbDisableEndpointsI(USBDriver *usbp) { push {r3, r4, r5, r6, r7, lr} osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state"); usbp->transmitting &= 1U; ldr r3, [r0, #8] and.w r3, r3, #65537 @ 0x10001 void usbDisableEndpointsI(USBDriver *usbp) { mov r4, r0 usbp->transmitting &= 1U; str r3, [r0, #8] usbp->receiving &= 1U; for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { add.w r5, r0, #12 add.w r6, r0, #40 @ 0x28 if (usbp->epc[i]->out_state != NULL) { osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); } } #endif usbp->epc[i] = NULL; movs r7, #0 if (usbp->epc[i] != NULL) { ldr.w r3, [r5, #4]! cbz r3, if (usbp->epc[i]->in_state != NULL) { ldr r0, [r3, #20] cbz r0, chThdResumeI(trp, msg); mvn.w r1, #1 adds r0, #12 bl if (usbp->epc[i]->out_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #24] cbz r0, mvn.w r1, #1 adds r0, #12 bl for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { cmp r5, r6 usbp->epc[i] = NULL; str r7, [r5, #0] for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { bne.n } /* Low level endpoints deactivation.*/ usb_lld_disable_endpoints(usbp); mov r0, r4 } ldmia.w sp!, {r3, r4, r5, r6, r7, lr} usb_lld_disable_endpoints(usbp); b.w : * the packet size because the excess is discarded. * * @iclass */ void usbStartReceiveI(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { push {r4, r5, r6, r7} /* Marking the endpoint as active.*/ usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); /* Setting up the transfer.*/ /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ osp = usbp->epc[ep]->out_state; add.w r4, r0, r1, lsl #2 usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); ldrh r7, [r0, #10] osp = usbp->epc[ep]->out_state; ldr r4, [r4, #12] usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); movs r5, #1 osp = usbp->epc[ep]->out_state; ldr r4, [r4, #24] usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); lsls r5, r1 orrs r5, r7 strh r5, [r0, #10] /*lint -restore*/ osp->rxbuf = buf; osp->rxsize = n; str r3, [r4, #0] osp->rxcnt = 0; movs r3, #0 osp->rxbuf = buf; str r2, [r4, #8] osp->rxcnt = 0; str r3, [r4, #4] #if USB_USE_WAIT == TRUE osp->thread = NULL; str r3, [r4, #12] #endif /* Starting transfer.*/ usb_lld_start_out(usbp, ep); } pop {r4, r5, r6, r7} usb_lld_start_out(usbp, ep); b.w : * @param[in] n transaction size * * @iclass */ void usbStartTransmitI(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) { push {r4, r5, r6, r7} /* Marking the endpoint as active.*/ usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); /* Setting up the transfer.*/ /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ isp = usbp->epc[ep]->in_state; add.w r4, r0, r1, lsl #2 usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); ldrh r7, [r0, #8] isp = usbp->epc[ep]->in_state; ldr r4, [r4, #12] usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); movs r5, #1 isp = usbp->epc[ep]->in_state; ldr r4, [r4, #20] usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); lsls r5, r1 orrs r5, r7 strh r5, [r0, #8] /*lint -restore*/ isp->txbuf = buf; isp->txsize = n; str r3, [r4, #0] isp->txcnt = 0; movs r3, #0 isp->txbuf = buf; str r2, [r4, #8] isp->txcnt = 0; str r3, [r4, #4] #if USB_USE_WAIT == TRUE isp->thread = NULL; str r3, [r4, #12] #endif /* Starting transfer.*/ usb_lld_start_in(usbp, ep); } pop {r4, r5, r6, r7} usb_lld_start_in(usbp, ep); b.w : if (usbp->state == USB_SUSPENDED) { /* Starting host wakeup procedure.*/ usb_lld_wakeup_host(usbp); } } bx lr <_usb_reset>: * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ void _usb_reset(USBDriver *usbp) { stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} /* Resetting internal state.*/ usbp->status = 0; usbp->address = 0; usbp->configuration = 0; usbp->transmitting = 0; mov r5, r0 usbp->status = 0; movs r6, #0 usbp->state = USB_READY; movs r3, #2 strb r3, [r0, #0] usbp->status = 0; str r6, [r0, #124] @ 0x7c usbp->transmitting = 0; str.w r6, [r5, #8]! void _usb_reset(USBDriver *usbp) { mov r4, r0 add.w r7, r0, #40 @ 0x28 mov.w r8, #48 @ 0x30 mov r9, r6 /* Invalidates all endpoints into the USBDriver structure.*/ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { #if USB_USE_WAIT == TRUE /* Signaling the event to threads waiting on endpoints.*/ if (usbp->epc[i] != NULL) { ldr.w r3, [r5, #4]! cbz r3, <_usb_reset+0x4c> msr BASEPRI, r8 osalSysLockFromISR(); if (usbp->epc[i]->in_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #20] cbz r0, <_usb_reset+0x38> mvn.w r1, #1 adds r0, #12 bl osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); } if (usbp->epc[i]->out_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #24] cbz r0, <_usb_reset+0x48> mvn.w r1, #1 adds r0, #12 bl msr BASEPRI, r9 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { cmp r5, r7 osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); } osalSysUnlockFromISR(); } #endif usbp->epc[i] = NULL; str r6, [r5, #0] for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { bne.n <_usb_reset+0x1e> } /* EP0 state machine initialization.*/ usbp->ep0state = USB_EP0_STP_WAITING; strb.w r6, [r4, #100] @ 0x64 /* Low level reset.*/ usb_lld_reset(usbp); mov r0, r4 bl /* Notification of reset event.*/ _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); ldr r3, [r4, #4] ldr r3, [r3, #0] cbz r3, <_usb_reset+0x6c> mov r0, r4 movs r1, #0 } ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, lr} _usb_isr_invoke_event_cb(usbp, USB_EVENT_RESET); bx r3 } ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} <_usb_suspend>: * * @param[in] usbp pointer to the @p USBDriver object * * @notapi */ void _usb_suspend(USBDriver *usbp) { push {r3, r4, r5, r6, r7, lr} /* It could happen that multiple suspend events are triggered.*/ if (usbp->state != USB_SUSPENDED) { ldrb r3, [r0, #0] cmp r3, #5 void _usb_suspend(USBDriver *usbp) { mov r4, r0 if (usbp->state != USB_SUSPENDED) { beq.n <_usb_suspend+0x5a> /* State transition, saving the current state.*/ usbp->saved_state = usbp->state; strb.w r3, [r0, #128] @ 0x80 usbp->state = USB_SUSPENDED; movs r3, #5 strb r3, [r0, #0] /* Notification of suspend event.*/ _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); ldr r3, [r0, #4] ldr r3, [r3, #0] cbz r3, <_usb_suspend+0x1c> movs r1, #4 blx r3 /* Terminating all pending transactions.*/ usbp->transmitting = 0; mov r5, r4 movs r6, #0 str.w r6, [r5, #8]! /* Signaling the event to threads waiting on endpoints.*/ #if USB_USE_WAIT == TRUE { unsigned i; for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { adds r4, #40 @ 0x28 movs r7, #48 @ 0x30 if (usbp->epc[i] != NULL) { ldr.w r3, [r5, #4]! cbz r3, <_usb_suspend+0x56> msr BASEPRI, r7 osalSysLockFromISR(); if (usbp->epc[i]->in_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #20] cbz r0, <_usb_suspend+0x42> mvn.w r1, #1 adds r0, #12 bl osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); } if (usbp->epc[i]->out_state != NULL) { ldr r3, [r5, #0] ldr r0, [r3, #24] cbz r0, <_usb_suspend+0x52> mvn.w r1, #1 adds r0, #12 bl msr BASEPRI, r6 for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { cmp r5, r4 bne.n <_usb_suspend+0x28> } } } #endif } } pop {r3, r4, r5, r6, r7, pc} <_usb_wakeup>: * @notapi */ void _usb_wakeup(USBDriver *usbp) { /* It could happen that multiple waakeup events are triggered.*/ if (usbp->state == USB_SUSPENDED) { ldrb r1, [r0, #0] cmp r1, #5 bne.n <_usb_wakeup+0x14> /* State transition, returning to the previous state.*/ usbp->state = usbp->saved_state; ldrb.w r2, [r0, #128] @ 0x80 /* Notification of suspend event.*/ _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); ldr r3, [r0, #4] usbp->state = usbp->saved_state; strb r2, [r0, #0] _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); ldr r3, [r3, #0] cbz r3, <_usb_wakeup+0x14> bx r3 } } bx lr <_usb_ep0setup>: * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number, always zero * * @notapi */ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { push {r4, r5, r6, lr} size_t max; /* Is the EP0 state machine in the correct state for handling setup packets?*/ if (usbp->ep0state != USB_EP0_STP_WAITING) { ldrb.w r3, [r0, #100] @ 0x64 void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { mov r4, r0 if (usbp->ep0state != USB_EP0_STP_WAITING) { cbz r3, <_usb_ep0setup+0x10> /* This is unexpected could require handling with a warning event.*/ /* CHTODO: handling here.*/ /* Resetting the EP0 state machine and going ahead.*/ usbp->ep0state = USB_EP0_STP_WAITING; movs r3, #0 strb.w r3, [r0, #100] @ 0x64 } /* Reading the setup data into the driver buffer.*/ usbReadSetup(usbp, ep, usbp->setup); add.w r2, r4, #116 @ 0x74 mov r0, r4 bl /* First verify if the application has an handler installed for this request.*/ /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ if ((usbp->config->requests_hook_cb == NULL) || ldr r3, [r4, #4] ldr r3, [r3, #8] cbnz r3, <_usb_ep0setup+0x4e> !(usbp->config->requests_hook_cb(usbp))) { /*lint -restore*/ /* Invoking the default handler, if this fails then stalls the endpoint zero as error.*/ /*lint -save -e9007 [13.5] No side effects, it is intentional.*/ if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) || ldrb.w r3, [r4, #116] @ 0x74 ands.w r5, r3, #96 @ 0x60 beq.n <_usb_ep0setup+0x9e> !default_handler(usbp)) { /*lint -restore*/ /* Error response, the state machine goes into an error state, the low level layer will have to reset it to USB_EP0_WAITING_SETUP after receiving a SETUP packet.*/ usb_lld_stall_in(usbp, 0); movs r1, #0 mov r0, r4 bl usb_lld_stall_out(usbp, 0); movs r1, #0 mov r0, r4 bl _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); ldr r3, [r4, #4] ldr r3, [r3, #0] cbz r3, <_usb_ep0setup+0x46> movs r1, #6 mov r0, r4 blx r3 usbp->ep0state = USB_EP0_ERROR; movs r3, #6 strb.w r3, [r4, #100] @ 0x64 #else usb_lld_end_setup(usbp, ep); #endif } } } pop {r4, r5, r6, pc} !(usbp->config->requests_hook_cb(usbp))) { mov r0, r4 blx r3 if ((usbp->config->requests_hook_cb == NULL) || cmp r0, #0 beq.n <_usb_ep0setup+0x20> max = (size_t)get_hword(&usbp->setup[6]); ldrb.w r2, [r4, #123] @ 0x7b ldrb.w r3, [r4, #122] @ 0x7a orr.w r3, r3, r2, lsl #8 if (usbp->ep0n > max) { ldr r2, [r4, #108] @ 0x6c cmp r2, r3 usbp->ep0n = max; it hi strhi r3, [r4, #108] @ 0x6c if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { ldrsb.w r3, [r4, #116] @ 0x74 if (usbp->ep0n != 0U) { ldr r5, [r4, #108] @ 0x6c if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { cmp r3, #0 mov.w r3, #48 @ 0x30 bge.w <_usb_ep0setup+0x28a> if (usbp->ep0n != 0U) { cmp r5, #0 beq.w <_usb_ep0setup+0x26e> usbp->ep0state = USB_EP0_IN_TX; movs r2, #9 strb.w r2, [r4, #100] @ 0x64 msr BASEPRI, r3 usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n); movs r1, #0 ldr r3, [r4, #108] @ 0x6c ldr r2, [r4, #104] @ 0x68 mov r0, r4 bl movs r3, #0 msr BASEPRI, r3 } b.n <_usb_ep0setup+0x4c> ((uint32_t)usbp->setup[1] << 8U))) { ldrb.w r2, [r4, #117] @ 0x75 switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | and.w r3, r3, #127 @ 0x7f USB_RTYPE_TYPE_MASK)) | orr.w r3, r3, r2, lsl #8 switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | movw r2, #770 @ 0x302 cmp r3, r2 beq.w <_usb_ep0setup+0x248> bhi.n <_usb_ep0setup+0xfa> cmp.w r3, #256 @ 0x100 beq.n <_usb_ep0setup+0x158> bhi.n <_usb_ep0setup+0xda> cmp r3, #1 beq.n <_usb_ep0setup+0x14c> cmp r3, #2 beq.w <_usb_ep0setup+0x1f8> cmp r3, #0 bne.n <_usb_ep0setup+0x2a> usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL); add.w r2, r4, #124 @ 0x7c str r2, [r4, #104] @ 0x68 movs r2, #2 str r2, [r4, #108] @ 0x6c usbSetupTransfer(usbp, NULL, 0, NULL); str r3, [r4, #112] @ 0x70 return true; b.n <_usb_ep0setup+0x56> switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | cmp.w r3, #258 @ 0x102 beq.w <_usb_ep0setup+0x222> cmp.w r3, #768 @ 0x300 bne.n <_usb_ep0setup+0x2a> if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { ldrb.w r3, [r4, #118] @ 0x76 cmp r3, #1 bne.n <_usb_ep0setup+0x2a> usbp->status |= 2U; ldrh.w r3, [r4, #124] @ 0x7c orr.w r3, r3, #2 b.n <_usb_ep0setup+0x16a> switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | cmp.w r3, #2048 @ 0x800 beq.n <_usb_ep0setup+0x1a6> bhi.n <_usb_ep0setup+0x13c> cmp.w r3, #1280 @ 0x500 beq.n <_usb_ep0setup+0x176> sub.w r3, r3, #1536 @ 0x600 cmp r3, #1 bhi.n <_usb_ep0setup+0x2a> dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], ldrb.w r2, [r4, #121] @ 0x79 ldr r1, [r4, #4] ldrb.w r3, [r4, #120] @ 0x78 ldr r6, [r1, #4] ldrb.w r1, [r4, #119] @ 0x77 orr.w r3, r3, r2, lsl #8 mov r0, r4 ldrb.w r2, [r4, #118] @ 0x76 blx r6 if (dp == NULL) { cmp r0, #0 beq.w <_usb_ep0setup+0x2a> usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); ldr r3, [r0, #4] str r3, [r4, #104] @ 0x68 ldr r3, [r0, #0] usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); str r3, [r4, #108] @ 0x6c b.n <_usb_ep0setup+0x172> switch ((((uint32_t)usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | cmp.w r3, #2304 @ 0x900 beq.n <_usb_ep0setup+0x1b0> movw r2, #3074 @ 0xc02 cmp r3, r2 bne.w <_usb_ep0setup+0x2a> usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL); ldr r3, [pc, #364] @ (<_usb_ep0setup+0x2bc>) usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); str r3, [r4, #104] @ 0x68 movs r3, #2 str r3, [r4, #108] @ 0x6c movs r3, #0 b.n <_usb_ep0setup+0xd6> if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { ldrb.w r3, [r4, #118] @ 0x76 cmp r3, #1 bne.w <_usb_ep0setup+0x2a> usbp->status &= ~2U; ldrh.w r3, [r4, #124] @ 0x7c bic.w r3, r3, #2 usbp->status |= 2U; strh.w r3, [r4, #124] @ 0x7c usbSetupTransfer(usbp, NULL, 0, NULL); str r5, [r4, #104] @ 0x68 str r5, [r4, #108] @ 0x6c usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); str r5, [r4, #112] @ 0x70 return true; b.n <_usb_ep0setup+0x56> if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) && ldrh.w r3, [r4, #116] @ 0x74 cmp.w r3, #1280 @ 0x500 bne.n <_usb_ep0setup+0x19e> usbp->address = usbp->setup[2]; ldrb.w r3, [r4, #118] @ 0x76 strb.w r3, [r4, #126] @ 0x7e usb_lld_set_address(usbp); mov r0, r4 bl _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS); ldr r3, [r4, #4] ldr r3, [r3, #0] cbz r3, <_usb_ep0setup+0x19a> movs r1, #1 mov r0, r4 blx r3 usbp->state = USB_SELECTED; movs r3, #3 strb r3, [r4, #0] usbSetupTransfer(usbp, NULL, 0, NULL); movs r3, #0 str r3, [r4, #104] @ 0x68 str r3, [r4, #108] @ 0x6c b.n <_usb_ep0setup+0xd6> usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); add.w r3, r4, #127 @ 0x7f str r3, [r4, #104] @ 0x68 movs r3, #1 b.n <_usb_ep0setup+0x138> if (usbp->state == USB_ACTIVE) { ldrb r3, [r4, #0] cmp r3, #4 bne.n <_usb_ep0setup+0x1d8> movs r3, #48 @ 0x30 msr BASEPRI, r3 usbDisableEndpointsI(usbp); mov r0, r4 bl msr BASEPRI, r5 usbp->state = USB_SELECTED; movs r1, #3 _usb_isr_invoke_event_cb(usbp, USB_EVENT_UNCONFIGURED); ldr r3, [r4, #4] usbp->configuration = 0U; strb.w r5, [r4, #127] @ 0x7f usbp->state = USB_SELECTED; strb r1, [r4, #0] _usb_isr_invoke_event_cb(usbp, USB_EVENT_UNCONFIGURED); ldr r3, [r3, #0] cbz r3, <_usb_ep0setup+0x1d8> mov r0, r4 blx r3 if (usbp->setup[2] != 0U) { ldrb.w r3, [r4, #118] @ 0x76 cmp r3, #0 beq.n <_usb_ep0setup+0x19e> usbp->configuration = usbp->setup[2]; strb.w r3, [r4, #127] @ 0x7f usbp->state = USB_ACTIVE; movs r3, #4 strb r3, [r4, #0] _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); ldr r3, [r4, #4] ldr r3, [r3, #0] cmp r3, #0 beq.n <_usb_ep0setup+0x19e> movs r1, #2 mov r0, r4 blx r3 b.n <_usb_ep0setup+0x19e> if ((usbp->setup[4] & 0x80U) != 0U) { ldrb.w r3, [r4, #120] @ 0x78 lsls r5, r3, #24 switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) { and.w r1, r3, #15 mov r0, r4 if ((usbp->setup[4] & 0x80U) != 0U) { bpl.n <_usb_ep0setup+0x21c> switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0FU)) { bl switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) { cmp r0, #1 beq.n <_usb_ep0setup+0x218> cmp r0, #2 bne.w <_usb_ep0setup+0x2a> usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); ldr r3, [pc, #168] @ (<_usb_ep0setup+0x2c0>) b.n <_usb_ep0setup+0x14e> usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); ldr r3, [pc, #168] @ (<_usb_ep0setup+0x2c4>) b.n <_usb_ep0setup+0x14e> switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0FU)) { bl b.n <_usb_ep0setup+0x20a> if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { ldrb.w r3, [r4, #118] @ 0x76 cmp r3, #0 bne.w <_usb_ep0setup+0x2a> if ((usbp->setup[4] & 0x0FU) != 0U) { ldrb.w r3, [r4, #120] @ 0x78 ands.w r1, r3, #15 beq.n <_usb_ep0setup+0x19e> if ((usbp->setup[4] & 0x80U) != 0U) { lsls r2, r3, #24 usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU); mov r0, r4 if ((usbp->setup[4] & 0x80U) != 0U) { bpl.n <_usb_ep0setup+0x242> usb_lld_clear_in(usbp, usbp->setup[4] & 0x0FU); bl b.n <_usb_ep0setup+0x19e> usb_lld_clear_out(usbp, usbp->setup[4] & 0x0FU); bl b.n <_usb_ep0setup+0x19e> if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) { ldrb.w r3, [r4, #118] @ 0x76 cmp r3, #0 bne.w <_usb_ep0setup+0x2a> if ((usbp->setup[4] & 0x0FU) != 0U) { ldrb.w r3, [r4, #120] @ 0x78 ands.w r1, r3, #15 beq.n <_usb_ep0setup+0x19e> if ((usbp->setup[4] & 0x80U) != 0U) { lsls r3, r3, #24 usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU); mov r0, r4 if ((usbp->setup[4] & 0x80U) != 0U) { bpl.n <_usb_ep0setup+0x268> usb_lld_stall_in(usbp, usbp->setup[4] & 0x0FU); bl b.n <_usb_ep0setup+0x19e> usb_lld_stall_out(usbp, usbp->setup[4] & 0x0FU); bl b.n <_usb_ep0setup+0x19e> usbp->ep0state = USB_EP0_OUT_WAITING_STS; movs r2, #20 strb.w r2, [r4, #100] @ 0x64 msr BASEPRI, r3 usbStartReceiveI(usbp, 0, NULL, 0); mov r3, r5 mov r2, r5 mov r1, r5 mov r0, r4 bl msr BASEPRI, r5 b.n <_usb_ep0setup+0x4c> if (usbp->ep0n != 0U) { cbz r5, <_usb_ep0setup+0x2a4> usbp->ep0state = USB_EP0_OUT_RX; movs r2, #21 strb.w r2, [r4, #100] @ 0x64 msr BASEPRI, r3 usbStartReceiveI(usbp, 0, (uint8_t *)usbp->ep0next, usbp->ep0n); movs r1, #0 ldr r3, [r4, #108] @ 0x6c ldr r2, [r4, #104] @ 0x68 mov r0, r4 bl b.n <_usb_ep0setup+0x96> usbp->ep0state = USB_EP0_IN_SENDING_STS; movs r2, #11 strb.w r2, [r4, #100] @ 0x64 msr BASEPRI, r3 usbStartTransmitI(usbp, 0, NULL, 0); mov r3, r5 mov r2, r5 mov r1, r5 mov r0, r4 bl b.n <_usb_ep0setup+0x284> .word 0x60008f94 .word 0x60008f92 .word 0x60008f90 <_usb_ep0in>: * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number, always zero * * @notapi */ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { push {r3, r4, r5, lr} size_t max; (void)ep; switch (usbp->ep0state) { ldrb.w r3, [r0, #100] @ 0x64 void _usb_ep0in(USBDriver *usbp, usbep_t ep) { mov r4, r0 switch (usbp->ep0state) { cmp r3, #0 beq.n <_usb_ep0in+0x92> subs r3, #6 uxtb r2, r3 cmp r2, #15 bhi.n <_usb_ep0in+0x86> cmp r3, #15 bhi.n <_usb_ep0in+0x86> tbb [pc, r3] .word 0x0835353b .word 0x35353626 .word 0x35353535 .word 0x3b3b3535 case USB_EP0_IN_TX: max = (size_t)get_hword(&usbp->setup[6]); ldrb.w r3, [r0, #122] @ 0x7a ldrb.w r2, [r0, #123] @ 0x7b /* If the transmitted size is less than the requested size and it is a multiple of the maximum packet size then a zero size packet must be transmitted.*/ if ((usbp->ep0n < max) && ldr r5, [r0, #108] @ 0x6c max = (size_t)get_hword(&usbp->setup[6]); orr.w r3, r3, r2, lsl #8 if ((usbp->ep0n < max) && cmp r5, r3 bcs.n <_usb_ep0in+0x68> ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) { ldr r3, [r0, #12] ldrh r3, [r3, #16] udiv r2, r5, r3 mls r5, r3, r2, r5 if ((usbp->ep0n < max) && cbnz r5, <_usb_ep0in+0x68> movs r3, #48 @ 0x30 msr BASEPRI, r3 osalSysLockFromISR(); usbStartTransmitI(usbp, 0, NULL, 0); mov r3, r5 mov r2, r5 mov r1, r5 bl msr BASEPRI, r5 osalSysUnlockFromISR(); usbp->ep0state = USB_EP0_IN_WAITING_TX0; movs r3, #10 level layer will have to reset it to USB_EP0_WAITING_SETUP after receiving a SETUP packet.*/ usb_lld_stall_in(usbp, 0); usb_lld_stall_out(usbp, 0); _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); usbp->ep0state = USB_EP0_ERROR; strb.w r3, [r4, #100] @ 0x64 return; b.n <_usb_ep0in+0x86> usbp->ep0state = USB_EP0_OUT_WAITING_STS; movs r3, #20 strb.w r3, [r4, #100] @ 0x64 movs r3, #48 @ 0x30 msr BASEPRI, r3 usbStartReceiveI(usbp, 0, NULL, 0); movs r3, #0 mov r2, r3 mov r1, r3 mov r0, r4 bl movs r3, #0 msr BASEPRI, r3 default: osalDbgAssert(false, "EP0 state machine invalid state"); } } pop {r3, r4, r5, pc} if (usbp->ep0endcb != NULL) { ldr r3, [r0, #112] @ 0x70 cbz r3, <_usb_ep0in+0x8e> usbp->ep0endcb(usbp); blx r3 usbp->ep0state = USB_EP0_STP_WAITING; movs r3, #0 b.n <_usb_ep0in+0x62> usb_lld_stall_in(usbp, 0); movs r1, #0 mov r0, r4 bl usb_lld_stall_out(usbp, 0); movs r1, #0 mov r0, r4 bl _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); ldr r3, [r4, #4] ldr r3, [r3, #0] cbz r3, <_usb_ep0in+0xae> movs r1, #6 mov r0, r4 blx r3 usbp->ep0state = USB_EP0_ERROR; movs r3, #6 b.n <_usb_ep0in+0x62> <_usb_ep0out>: * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number, always zero * * @notapi */ void _usb_ep0out(USBDriver *usbp, usbep_t ep) { push {r4, lr} (void)ep; switch (usbp->ep0state) { ldrb.w r3, [r0, #100] @ 0x64 cmp r3, #20 void _usb_ep0out(USBDriver *usbp, usbep_t ep) { mov r4, r0 switch (usbp->ep0state) { beq.n <_usb_ep0out+0x60> bhi.n <_usb_ep0out+0x3e> cmp r3, #6 beq.n <_usb_ep0out+0x1e> bhi.n <_usb_ep0out+0x18> cbz r3, <_usb_ep0out+0x1e> usbp->ep0state = USB_EP0_ERROR; return; default: osalDbgAssert(false, "EP0 state machine invalid state"); } } pop {r4, pc} switch (usbp->ep0state) { subs r3, #9 cmp r3, #2 bhi.n <_usb_ep0out+0x16> usb_lld_stall_in(usbp, 0); movs r1, #0 mov r0, r4 bl usb_lld_stall_out(usbp, 0); movs r1, #0 mov r0, r4 bl _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); ldr r3, [r4, #4] ldr r3, [r3, #0] cbz r3, <_usb_ep0out+0x3a> movs r1, #6 mov r0, r4 blx r3 usbp->ep0state = USB_EP0_ERROR; movs r3, #6 b.n <_usb_ep0out+0x72> switch (usbp->ep0state) { cmp r3, #21 bne.n <_usb_ep0out+0x16> usbp->ep0state = USB_EP0_IN_SENDING_STS; movs r3, #11 strb.w r3, [r0, #100] @ 0x64 movs r3, #48 @ 0x30 msr BASEPRI, r3 usbStartTransmitI(usbp, 0, NULL, 0); movs r3, #0 mov r2, r3 mov r1, r3 bl movs r3, #0 msr BASEPRI, r3 b.n <_usb_ep0out+0x16> if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) { ldr r3, [r0, #12] ldr r3, [r3, #24] ldr r3, [r3, #4] cmp r3, #0 bne.n <_usb_ep0out+0x16> if (usbp->ep0endcb != NULL) { ldr r3, [r0, #112] @ 0x70 cbz r3, <_usb_ep0out+0x70> usbp->ep0endcb(usbp); blx r3 usbp->ep0state = USB_EP0_STP_WAITING; movs r3, #0 usbp->ep0state = USB_EP0_ERROR; strb.w r3, [r4, #100] @ 0x64 return; b.n <_usb_ep0out+0x16> <__chibios_override___early_init>: /** * @brief Early initialization code. * @details This initialization must be performed just after stack setup * and before any other initialization. */ void __early_init(void) { bx lr <__late_init>: } void __late_init(void) { push {r3, lr} MIMXRT1062_clock_init(); bl MIMXRT1062_MPU_init(); } ldmia.w sp!, {r3, lr} MIMXRT1062_MPU_init(); b.w <__chibios_override_boardInit>: /** * @brief Board-specific initialization code. * @todo Add your board-specific code, if any. */ void boardInit(void) { } bx lr <_read_r>: return len; #else (void)file; (void)ptr; (void)len; __errno_r(r) = EINVAL; movs r3, #22 str r3, [r0, #0] return -1; #endif } mov.w r0, #4294967295 @ 0xffffffff bx lr <_lseek_r>: (void)file; (void)ptr; (void)dir; return 0; } movs r0, #0 bx lr <_write_r>: return -1; } sdWrite(&STDOUT_SD, (uint8_t *)ptr, (size_t)len); #endif return len; } mov r0, r3 bx lr <_close_r>: int _close_r(struct _reent *r, int file) { (void)r; (void)file; return 0; } movs r0, #0 bx lr <_sbrk_r>: /***************************************************************************/ __attribute__((used)) caddr_t _sbrk_r(struct _reent *r, int incr) { push {r4, lr} #if CH_CFG_USE_MEMCORE void *p; chDbgCheck(incr >= 0); p = chCoreAllocFromBase((size_t)incr, 1U, 0U); movs r2, #0 caddr_t _sbrk_r(struct _reent *r, int incr) { mov r4, r0 mov r0, r1 p = chCoreAllocFromBase((size_t)incr, 1U, 0U); movs r1, #1 bl if (p == NULL) { cbnz r0, <_sbrk_r+0x18> __errno_r(r) = ENOMEM; movs r3, #12 str r3, [r4, #0] return (caddr_t)-1; mov.w r0, #4294967295 @ 0xffffffff #else (void)incr; __errno_r(r) = ENOMEM; return (caddr_t)-1; #endif } pop {r4, pc} <_fstat_r>: /***************************************************************************/ __attribute__((used)) int _fstat_r(struct _reent *r, int file, struct stat * st) { push {r3, lr} mov r3, r2 (void)r; (void)file; memset(st, 0, sizeof(*st)); movs r1, #0 movs r2, #88 @ 0x58 mov r0, r3 bl st->st_mode = S_IFCHR; mov.w r2, #8192 @ 0x2000 str r2, [r0, #4] return 0; } movs r0, #0 pop {r3, pc} <_isatty_r>: int _isatty_r(struct _reent *r, int fd) { (void)r; (void)fd; return 1; } movs r0, #1 bx lr <_exit>: /***************************************************************************/ __attribute__((used)) void _exit(int status) { push {r3, lr} (void) status; chSysHalt("exit"); ldr r0, [pc, #8] @ (<_exit+0xc>) bl abort(); bl .word 0x60008e49 <_kill>: } /***************************************************************************/ __attribute__((used)) int _kill(int pid, int sig) { push {r3, lr} (void) pid; (void) sig; chSysHalt("kill"); ldr r0, [pc, #8] @ (<_kill+0xc>) bl abort(); bl .word 0x60008e4e <_getpid>: __attribute__((used)) int _getpid(void) { return 1; abort(); } movs r0, #1 bx lr <_fini>: return 1; } __attribute__((weak, used)) void _fini(void) { return; } bx lr : #if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC) || \ defined(__CORE_CM23_H_GENERIC) NVIC->__IPR[_IP_IDX(n)] = (NVIC->__IPR[_IP_IDX(n)] & ~(0xFFU << _BIT_SHIFT(n))) | (NVIC_PRIORITY_MASK(prio) << _BIT_SHIFT(n)); #else NVIC->__IPR[n] = NVIC_PRIORITY_MASK(prio); add.w r3, r0, #3758096384 @ 0xe0000000 add.w r3, r3, #57600 @ 0xe100 lsls r1, r1, #4 uxtb r1, r1 strb.w r1, [r3, #768] @ 0x300 #endif NVIC->__ICPR[n >> 5U] = 1U << (n & 0x1FU); movs r2, #1 and.w r3, r0, #31 lsls r2, r3 lsrs r3, r0, #5 lsls r3, r3, #2 add.w r3, r3, #3758096384 @ 0xe0000000 add.w r3, r3, #57600 @ 0xe100 str.w r2, [r3, #384] @ 0x180 NVIC->__ISER[n >> 5U] = 1U << (n & 0x1FU); str r2, [r3, #0] #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3) /* If the IRQ is enabled from secure mode then it is marked as secure interrupt in ITNS.*/ NVIC->__ITNS[n >> 5U] &= ~(1U << (n & 0x1FU)); #endif } bx lr : * * @param[in] n the interrupt number */ void nvicDisableVector(uint32_t n) { NVIC->__ICER[n >> 5U] = 1U << (n & 0x1FU); and.w r3, r0, #31 movs r2, #1 lsls r2, r3 lsrs r3, r0, #5 lsls r3, r3, #2 add.w r3, r3, #3758096384 @ 0xe0000000 add.w r3, r3, #57600 @ 0xe100 NVIC->__ICPR[n >> 5U] = 1U << (n & 0x1FU); #if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC) || \ defined(__CORE_CM23_H_GENERIC) NVIC->__IPR[_IP_IDX(n)] = NVIC->__IPR[_IP_IDX(n)] & ~(0xFFU << _BIT_SHIFT(n)); #else NVIC->__IPR[n] = 0U; add.w r0, r0, #3758096384 @ 0xe0000000 add.w r0, r0, #57600 @ 0xe100 NVIC->__ICER[n >> 5U] = 1U << (n & 0x1FU); str.w r2, [r3, #128] @ 0x80 NVIC->__ICPR[n >> 5U] = 1U << (n & 0x1FU); str.w r2, [r3, #384] @ 0x180 NVIC->__IPR[n] = 0U; movs r3, #0 strb.w r3, [r0, #768] @ 0x300 #endif #if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3) /* Marked as not secure again.*/ NVIC->__ITNS[n >> 5U] |= 1U << (n & 0x1FU); #endif } bx lr : #if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC) || \ defined(__CORE_CM23_H_GENERIC) SCB->__SHPR[_SHP_IDX(handler)] = (SCB->__SHPR[_SHP_IDX(handler)] & ~(0xFFU << _BIT_SHIFT(handler))) | (NVIC_PRIORITY_MASK(prio) << _BIT_SHIFT(handler)); #else SCB->__SHPR[handler] = NVIC_PRIORITY_MASK(prio); add.w r0, r0, #3758096384 @ 0xe0000000 lsls r1, r1, #4 add.w r0, r0, #60672 @ 0xed00 uxtb r1, r1 strb r1, [r0, #24] #endif } bx lr : * @todo Use a macro to define the system clock frequency. * * @notapi */ void hal_lld_init(void) { } bx lr : volatile uint32_t *reg; assert(index <= 7UL); reg = (volatile uint32_t *)(&(((volatile uint32_t *)&CCM->CCGR0)[index])); *reg = ((*reg) & ~((uint32_t)(3UL << shift))) | (((uint32_t)value) << shift); ldr r2, [pc, #60] @ () #define NVIC_NUM_INTERRUPTS 160 extern uint32_t _vectors[NVIC_NUM_INTERRUPTS]; uint32_t SystemCoreClock = 528000000UL; // default system clock void MIMXRT1062_clock_init(void) { push {r3, lr} ldr r3, [r2, #120] @ 0x78 orr.w r3, r3, #12 str r3, [r2, #120] @ 0x78 // We need the IOMUXC for GPIO to work. We do not need BOARD_InitPins() from // the NXP SDK, we use the ChibiOS PAL HAL instead. CLOCK_EnableClock(kCLOCK_Iomuxc); BOARD_InitBootClocks(); bl // Configure the GPIO pins from the standard-speed GPIOs onto the high-speed // GPIOs GPIO6, GPIO7, GPIO8, and GPIO9: // // See also IMXRT1060RM, page 949, 12.1 Chip-specific GPIO information. IOMUXC_GPR->GPR26 = 0xFFFFFFFF; ldr r3, [pc, #48] @ () mov.w r2, #4294967295 @ 0xffffffff str r2, [r3, #104] @ 0x68 IOMUXC_GPR->GPR27 = 0xFFFFFFFF; str r2, [r3, #108] @ 0x6c IOMUXC_GPR->GPR28 = 0xFFFFFFFF; str r2, [r3, #112] @ 0x70 IOMUXC_GPR->GPR29 = 0xFFFFFFFF; str r2, [r3, #116] @ 0x74 // Turn on the Teensy power LED on pin 13, which users generally expect: IOMUXC->SW_MUX_CTL_PAD[kIOMUXC_SW_MUX_CTL_PAD_GPIO_B0_03] = add.w r3, r3, #1359872 @ 0x14c000 movs r2, #5 str.w r2, [r3, #328] @ 0x148 PIN_MUX_ALTERNATIVE(5); GPIO7->GDIR |= ((uint32_t) 1 << 3); ldr r3, [pc, #28] @ () ldr r2, [r3, #4] orr.w r2, r2, #8 str r2, [r3, #4] GPIO7->DR_SET = ((uint32_t) 1 << 3); movs r2, #8 str.w r2, [r3, #132] @ 0x84 printf_debug("\n***********IMXRT Chibi Startup**********\n"); printf_debug("test %d %d %d\n", 1, -1234567, 3); // Explicitly warn for a few issues I ran into, to catch possible // problems automatically when working on startup code: if (SCB->VTOR != (uint32_t)&_vectors) { ldr r3, [pc, #16] @ () ldr r3, [r3, #8] printf_debug("WARNING: &_vectors = %x is unexpectedly not aligned by 4\n", (uint32_t)&_vectors); } if (CORTEX_NUM_VECTORS != 160) { printf_debug("WARNING: unexpected CORTEX_NUM_VECTORS = %d, want %d", CORTEX_NUM_VECTORS, 160); } } pop {r3, pc} nop .word 0x400fc000 .word 0x400ac000 .word 0x42004000 .word 0xe000ed00 : { push {r3, r4, r5, lr} CCM_TUPLE_REG(CCM, divider) = (CCM_TUPLE_REG(CCM, divider) & (~CCM_TUPLE_MASK(divider))) | uxtb r3, r0 add.w r3, r3, #1073741824 @ 0x40000000 add.w r3, r3, #1032192 @ 0xfc000 ubfx r5, r0, #8, #5 ldr r4, [r3, #0] busyShift = CCM_TUPLE_BUSY_SHIFT(divider); lsrs r2, r0, #26 (((uint32_t)((value) << CCM_TUPLE_SHIFT(divider))) & CCM_TUPLE_MASK(divider)); lsls r1, r5 CCM_TUPLE_REG(CCM, divider) = (CCM_TUPLE_REG(CCM, divider) & (~CCM_TUPLE_MASK(divider))) | ubfx r0, r0, #13, #13 lsls r0, r5 eors r1, r4 ands r0, r1 eors r0, r4 assert(busyShift <= CCM_NO_BUSY_WAIT); cmp r2, #32 CCM_TUPLE_REG(CCM, divider) = (CCM_TUPLE_REG(CCM, divider) & (~CCM_TUPLE_MASK(divider))) | str r0, [r3, #0] assert(busyShift <= CCM_NO_BUSY_WAIT); bls.n ldr r3, [pc, #28] @ () ldr r2, [pc, #32] @ () ldr r0, [pc, #32] @ () movw r1, #1183 @ 0x49f bl <__assert_func> if (CCM_NO_BUSY_WAIT != busyShift) beq.n movs r3, #1 while ((CCM->CDHIPR & ((uint32_t)(1UL << busyShift))) != 0UL) ldr r1, [pc, #24] @ () lsls r3, r2 ldr r2, [r1, #72] @ 0x48 tst r3, r2 bne.n } pop {r3, r4, r5, pc} nop .word 0x60008e53 .word 0x60008fa3 .word 0x60008e71 .word 0x400fc000 : { push {r3, r4, r5, lr} CCM_TUPLE_REG(CCM, mux) = (CCM_TUPLE_REG(CCM, mux) & (~CCM_TUPLE_MASK(mux))) | uxtb r3, r0 add.w r3, r3, #1073741824 @ 0x40000000 add.w r3, r3, #1032192 @ 0xfc000 ubfx r5, r0, #8, #5 ldr r4, [r3, #0] busyShift = (uint32_t)CCM_TUPLE_BUSY_SHIFT(mux); lsrs r2, r0, #26 (((uint32_t)((value) << CCM_TUPLE_SHIFT(mux))) & CCM_TUPLE_MASK(mux)); lsls r1, r5 CCM_TUPLE_REG(CCM, mux) = (CCM_TUPLE_REG(CCM, mux) & (~CCM_TUPLE_MASK(mux))) | ubfx r0, r0, #13, #13 lsls r0, r5 eors r1, r4 ands r0, r1 eors r0, r4 assert(busyShift <= CCM_NO_BUSY_WAIT); cmp r2, #32 CCM_TUPLE_REG(CCM, mux) = (CCM_TUPLE_REG(CCM, mux) & (~CCM_TUPLE_MASK(mux))) | str r0, [r3, #0] assert(busyShift <= CCM_NO_BUSY_WAIT); bls.n ldr r3, [pc, #28] @ () ldr r2, [pc, #32] @ () ldr r0, [pc, #32] @ () movw r1, #1146 @ 0x47a bl <__assert_func> if (CCM_NO_BUSY_WAIT != busyShift) beq.n movs r3, #1 while ((CCM->CDHIPR & ((1UL << busyShift))) != 0UL) ldr r1, [pc, #24] @ () lsls r3, r2 ldr r2, [r1, #72] @ 0x48 tst r3, r2 bne.n } pop {r3, r4, r5, pc} nop .word 0x60008e53 .word 0x60008f96 .word 0x60008e71 .word 0x400fc000 : * @brief Disable the clock for specific IP. * * @param name Which clock to disable, see \ref clock_ip_name_t. */ static inline void CLOCK_DisableClock(clock_ip_name_t name) { push {r4, lr} reg = (volatile uint32_t *)(&(((volatile uint32_t *)&CCM->CCGR0)[index])); ldr r1, [pc, #24] @ () uint32_t index = ((uint32_t)name) >> 8U; lsrs r4, r0, #8 *reg = ((*reg) & ~((uint32_t)(3UL << shift))) | (((uint32_t)value) << shift); movs r2, #3 ldr.w r3, [r1, r4, lsl #2] uint32_t shift = ((uint32_t)name) & 0x1FU; and.w r0, r0, #31 *reg = ((*reg) & ~((uint32_t)(3UL << shift))) | (((uint32_t)value) << shift); lsls r2, r0 bic.w r3, r3, r2 str.w r3, [r1, r4, lsl #2] CLOCK_ControlGate(name, kCLOCK_ClockNotNeeded); } pop {r4, pc} .word 0x400fc068 : }; /******************************************************************************* * Code for BOARD_BootClockRUN configuration ******************************************************************************/ void BOARD_BootClockRUN(void) { push {r3, r4, r5, lr} * * @param freq The RTC XTAL input clock frequency in Hz. */ static inline void CLOCK_SetRtcXtalFreq(uint32_t freq) { g_rtcXtalFreq = freq; ldr r3, [pc, #884] @ () mov.w r2, #32768 @ 0x8000 str r2, [r3, #0] /* Init RTC OSC clock frequency. */ CLOCK_SetRtcXtalFreq(32768U); /* Enable 1MHz clock output. */ XTALOSC24M->OSC_CONFIG2 |= XTALOSC24M_OSC_CONFIG2_ENABLE_1M_MASK; ldr r3, [pc, #880] @ () ldr.w r2, [r3, #704] @ 0x2c0 orr.w r2, r2, #65536 @ 0x10000 str.w r2, [r3, #704] @ 0x2c0 /* Use free 1MHz clock output. */ XTALOSC24M->OSC_CONFIG2 &= ~XTALOSC24M_OSC_CONFIG2_MUX_1M_MASK; ldr.w r2, [r3, #704] @ 0x2c0 bic.w r2, r2, #131072 @ 0x20000 str.w r2, [r3, #704] @ 0x2c0 g_xtalFreq = freq; ldr r3, [pc, #856] @ () ldr r2, [pc, #860] @ () str r2, [r3, #0] /* Set XTAL 24MHz clock frequency. */ CLOCK_SetXtalFreq(24000000U); /* Enable XTAL 24MHz clock source. */ CLOCK_InitExternalClk(0); movs r0, #0 bl /* Enable internal RC. */ CLOCK_InitRcOsc24M(); bl /* Switch clock source to external OSC. */ CLOCK_SwitchOsc(kCLOCK_XtalOsc); movs r0, #1 bl /* Set Oscillator ready counter value. */ CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127); ldr r2, [pc, #844] @ () /* Setting PeriphClk2Mux and PeriphMux to provide stable clock before PLLs are initialed */ CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */ ldr r0, [pc, #844] @ () CCM->CCR = (CCM->CCR & (~CCM_CCR_OSCNT_MASK)) | CCM_CCR_OSCNT(127); ldr r3, [r2, #0] bic.w r3, r3, #255 @ 0xff orr.w r3, r3, #127 @ 0x7f str r3, [r2, #0] CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 1); /* Set PERIPH_CLK2 MUX to OSC */ movs r1, #1 bl CLOCK_SetMux(kCLOCK_PeriphMux, 1); /* Set PERIPH_CLK MUX to PERIPH_CLK2 */ ldr r0, [pc, #828] @ () movs r1, #1 bl /* Setting the VDD_SOC to 1.275V. It is necessary to config AHB to 600Mhz. */ DCDC->REG3 = (DCDC->REG3 & (~DCDC_REG3_TRG_MASK)) | DCDC_REG3_TRG(0x13); ldr r2, [pc, #824] @ () ldr r3, [r2, #12] bic.w r3, r3, #31 orr.w r3, r3, #19 str r3, [r2, #12] /* Waiting for DCDC_STS_DC_OK bit is asserted */ while (DCDC_REG0_STS_DC_OK_MASK != (DCDC_REG0_STS_DC_OK_MASK & DCDC->REG0)) ldr r3, [r2, #0] cmp r3, #0 bge.n { } /* Set AHB_PODF. */ CLOCK_SetDiv(kCLOCK_AhbDiv, 0); movs r1, #0 ldr r0, [pc, #808] @ () */ static inline void CLOCK_SetPllBypass(CCM_ANALOG_Type *base, clock_pll_t pll, bool bypass) { if (bypass) { CCM_ANALOG_TUPLE_REG_OFF(base, pll, 4U) = 1UL << CCM_ANALOG_PLL_BYPASS_SHIFT; ldr r4, [pc, #776] @ () bl /* Disable IPG clock gate. */ CLOCK_DisableClock(kCLOCK_Adc1); mov.w r0, #272 @ 0x110 bl CLOCK_DisableClock(kCLOCK_Adc2); mov.w r0, #264 @ 0x108 bl CLOCK_DisableClock(kCLOCK_Xbar1); movw r0, #534 @ 0x216 bl CLOCK_DisableClock(kCLOCK_Xbar2); mov.w r0, #536 @ 0x218 bl CLOCK_DisableClock(kCLOCK_Xbar3); movw r0, #526 @ 0x20e bl /* Set IPG_PODF. */ CLOCK_SetDiv(kCLOCK_IpgDiv, 3); ldr r0, [pc, #764] @ () movs r1, #3 bl /* Set ARM_PODF. */ CLOCK_SetDiv(kCLOCK_ArmDiv, 1); ldr r0, [pc, #760] @ () movs r1, #1 bl /* Set PERIPH_CLK2_PODF. */ CLOCK_SetDiv(kCLOCK_PeriphClk2Div, 0); movs r1, #0 ldr r0, [pc, #752] @ () bl /* Disable PERCLK clock gate. */ CLOCK_DisableClock(kCLOCK_Gpt1); mov.w r0, #276 @ 0x114 bl CLOCK_DisableClock(kCLOCK_Gpt1S); mov.w r0, #278 @ 0x116 bl CLOCK_DisableClock(kCLOCK_Gpt2); movs r0, #24 bl CLOCK_DisableClock(kCLOCK_Gpt2S); movs r0, #26 bl CLOCK_DisableClock(kCLOCK_Pit); mov.w r0, #268 @ 0x10c bl /* Set PERCLK_PODF. */ CLOCK_SetDiv(kCLOCK_PerclkDiv, 1); movs r1, #1 ldr r0, [pc, #712] @ () bl /* Disable USDHC1 clock gate. */ CLOCK_DisableClock(kCLOCK_Usdhc1); movw r0, #1538 @ 0x602 bl /* Set USDHC1_PODF. */ CLOCK_SetDiv(kCLOCK_Usdhc1Div, 1); ldr r0, [pc, #704] @ () movs r1, #1 bl /* Set Usdhc1 clock source. */ CLOCK_SetMux(kCLOCK_Usdhc1Mux, 0); movs r1, #0 ldr r0, [pc, #696] @ () bl /* Disable USDHC2 clock gate. */ CLOCK_DisableClock(kCLOCK_Usdhc2); movw r0, #1540 @ 0x604 bl /* Set USDHC2_PODF. */ CLOCK_SetDiv(kCLOCK_Usdhc2Div, 1); ldr r0, [pc, #688] @ () movs r1, #1 bl /* Set Usdhc2 clock source. */ CLOCK_SetMux(kCLOCK_Usdhc2Mux, 0); movs r1, #0 ldr r0, [pc, #680] @ () bl /* In SDK projects, SDRAM (configured by SEMC) will be initialized in either debug script or dcd. * With this macro SKIP_SYSCLK_INIT, system pll (selected to be SEMC source clock in SDK projects) will be left unchanged. * Note: If another clock source is selected for SEMC, user may want to avoid changing that clock as well.*/ #ifndef SKIP_SYSCLK_INIT /* Disable Semc clock gate. */ CLOCK_DisableClock(kCLOCK_Semc); mov.w r0, #772 @ 0x304 bl /* Set SEMC_PODF. */ CLOCK_SetDiv(kCLOCK_SemcDiv, 7); movs r1, #7 movw r0, #61460 @ 0xf014 bl /* Set Semc alt clock source. */ CLOCK_SetMux(kCLOCK_SemcAltMux, 0); ldr r0, [pc, #660] @ () movs r1, #0 bl /* Set Semc clock source. */ CLOCK_SetMux(kCLOCK_SemcMux, 0); movs r1, #0 ldr r0, [pc, #656] @ () bl CLOCK_SetDiv(kCLOCK_CsiDiv, 1); /* Set Csi clock source. */ CLOCK_SetMux(kCLOCK_CsiMux, 0); #endif /* Disable LPSPI clock gate. */ CLOCK_DisableClock(kCLOCK_Lpspi1); mov.w r0, #256 @ 0x100 bl CLOCK_DisableClock(kCLOCK_Lpspi2); mov.w r0, #258 @ 0x102 bl CLOCK_DisableClock(kCLOCK_Lpspi3); mov.w r0, #260 @ 0x104 bl CLOCK_DisableClock(kCLOCK_Lpspi4); mov.w r0, #262 @ 0x106 bl /* Set LPSPI_PODF. */ CLOCK_SetDiv(kCLOCK_LpspiDiv, 4); ldr r0, [pc, #620] @ () movs r1, #4 bl /* Set Lpspi clock source. */ CLOCK_SetMux(kCLOCK_LpspiMux, 2); movs r1, #2 ldr r0, [pc, #616] @ () bl /* Disable TRACE clock gate. */ CLOCK_DisableClock(kCLOCK_Trace); movs r0, #22 bl /* Set TRACE_PODF. */ CLOCK_SetDiv(kCLOCK_TraceDiv, 3); ldr r0, [pc, #608] @ () movs r1, #3 bl /* Set Trace clock source. */ CLOCK_SetMux(kCLOCK_TraceMux, 0); movs r1, #0 ldr r0, [pc, #600] @ () bl /* Disable SAI1 clock gate. */ CLOCK_DisableClock(kCLOCK_Sai1); movw r0, #1298 @ 0x512 bl /* Set SAI1_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Sai1PreDiv, 3); ldr r0, [pc, #592] @ () movs r1, #3 bl /* Set SAI1_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Sai1Div, 1); ldr r0, [pc, #588] @ () movs r1, #1 bl /* Set Sai1 clock source. */ CLOCK_SetMux(kCLOCK_Sai1Mux, 0); movs r1, #0 ldr r0, [pc, #580] @ () bl /* Disable SAI2 clock gate. */ CLOCK_DisableClock(kCLOCK_Sai2); movw r0, #1300 @ 0x514 bl /* Set SAI2_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Sai2PreDiv, 3); ldr r0, [pc, #572] @ () movs r1, #3 bl /* Set SAI2_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Sai2Div, 1); ldr r0, [pc, #568] @ () movs r1, #1 bl /* Set Sai2 clock source. */ CLOCK_SetMux(kCLOCK_Sai2Mux, 0); movs r1, #0 ldr r0, [pc, #560] @ () bl /* Disable SAI3 clock gate. */ CLOCK_DisableClock(kCLOCK_Sai3); movw r0, #1302 @ 0x516 bl /* Set SAI3_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Sai3PreDiv, 3); ldr r0, [pc, #552] @ () movs r1, #3 bl /* Set SAI3_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Sai3Div, 1); ldr r0, [pc, #548] @ () movs r1, #1 bl /* Set Sai3 clock source. */ CLOCK_SetMux(kCLOCK_Sai3Mux, 0); movs r1, #0 ldr r0, [pc, #540] @ () bl /* Disable Lpi2c clock gate. */ CLOCK_DisableClock(kCLOCK_Lpi2c1); movw r0, #518 @ 0x206 bl CLOCK_DisableClock(kCLOCK_Lpi2c2); mov.w r0, #520 @ 0x208 bl CLOCK_DisableClock(kCLOCK_Lpi2c3); movw r0, #522 @ 0x20a bl /* Set LPI2C_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Lpi2cDiv, 0); ldr r0, [pc, #516] @ () movs r1, #0 bl /* Set Lpi2c clock source. */ CLOCK_SetMux(kCLOCK_Lpi2cMux, 0); movs r1, #0 ldr r0, [pc, #508] @ () bl /* Disable CAN clock gate. */ CLOCK_DisableClock(kCLOCK_Can1); movs r0, #14 bl CLOCK_DisableClock(kCLOCK_Can2); movs r0, #18 bl CLOCK_DisableClock(kCLOCK_Can3); movw r0, #1798 @ 0x706 bl CLOCK_DisableClock(kCLOCK_Can1S); movs r0, #16 bl CLOCK_DisableClock(kCLOCK_Can2S); movs r0, #20 bl CLOCK_DisableClock(kCLOCK_Can3S); mov.w r0, #1800 @ 0x708 bl /* Set CAN_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_CanDiv, 1); ldr r0, [pc, #468] @ () movs r1, #1 bl /* Set Can clock source. */ CLOCK_SetMux(kCLOCK_CanMux, 2); movs r1, #2 ldr r0, [pc, #460] @ () bl /* Disable UART clock gate. */ CLOCK_DisableClock(kCLOCK_Lpuart1); mov.w r0, #1304 @ 0x518 bl CLOCK_DisableClock(kCLOCK_Lpuart2); movs r0, #28 bl CLOCK_DisableClock(kCLOCK_Lpuart3); movs r0, #12 bl CLOCK_DisableClock(kCLOCK_Lpuart4); mov.w r0, #280 @ 0x118 bl CLOCK_DisableClock(kCLOCK_Lpuart5); movw r0, #770 @ 0x302 bl CLOCK_DisableClock(kCLOCK_Lpuart6); movw r0, #774 @ 0x306 bl CLOCK_DisableClock(kCLOCK_Lpuart7); movw r0, #1306 @ 0x51a bl CLOCK_DisableClock(kCLOCK_Lpuart8); movw r0, #1550 @ 0x60e bl /* Set UART_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_UartDiv, 0); ldr r0, [pc, #400] @ () movs r1, #0 bl /* Set Uart clock source. */ CLOCK_SetMux(kCLOCK_UartMux, 0); movs r1, #0 ldr r0, [pc, #392] @ () bl /* Disable LCDIF clock gate. */ CLOCK_DisableClock(kCLOCK_LcdPixel); movw r0, #778 @ 0x30a bl /* Set LCDIF_PRED. */ CLOCK_SetDiv(kCLOCK_LcdifPreDiv, 1); ldr r0, [pc, #384] @ () movs r1, #1 bl /* Set LCDIF_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_LcdifDiv, 3); ldr r0, [pc, #380] @ () movs r1, #3 bl /* Set Lcdif pre clock source. */ CLOCK_SetMux(kCLOCK_LcdifPreMux, 5); movs r1, #5 ldr r0, [pc, #372] @ () bl /* Disable SPDIF clock gate. */ CLOCK_DisableClock(kCLOCK_Spdif); movw r0, #1294 @ 0x50e bl /* Set SPDIF0_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Spdif0PreDiv, 1); ldr r0, [pc, #364] @ () movs r1, #1 bl /* Set SPDIF0_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Spdif0Div, 7); ldr r0, [pc, #360] @ () movs r1, #7 bl /* Set Spdif clock source. */ CLOCK_SetMux(kCLOCK_SpdifMux, 3); movs r1, #3 ldr r0, [pc, #352] @ () bl /* Disable Flexio1 clock gate. */ CLOCK_DisableClock(kCLOCK_Flexio1); movw r0, #1282 @ 0x502 bl /* Set FLEXIO1_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Flexio1PreDiv, 1); ldr r0, [pc, #344] @ () movs r1, #1 bl /* Set FLEXIO1_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Flexio1Div, 7); ldr r0, [pc, #340] @ () movs r1, #7 bl /* Set Flexio1 clock source. */ CLOCK_SetMux(kCLOCK_Flexio1Mux, 3); movs r1, #3 ldr r0, [pc, #332] @ () bl /* Disable Flexio2 clock gate. */ CLOCK_DisableClock(kCLOCK_Flexio2); mov.w r0, #768 @ 0x300 bl /* Set FLEXIO2_CLK_PRED. */ CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, 1); ldr r0, [pc, #324] @ () movs r1, #1 bl /* Set FLEXIO2_CLK_PODF. */ CLOCK_SetDiv(kCLOCK_Flexio2Div, 7); ldr r0, [pc, #320] @ () movs r1, #7 bl /* Set Flexio2 clock source. */ CLOCK_SetMux(kCLOCK_Flexio2Mux, 3); ldr r0, [pc, #316] @ () movs r1, #3 bl /* Set Pll3 sw clock source. */ CLOCK_SetMux(kCLOCK_Pll3SwMux, 0); movs r1, #0 ldr r0, [pc, #308] @ () bl /* Init ARM PLL. */ CLOCK_InitArmPll(&armPllConfig_BOARD_BootClockRUN); ldr r0, [pc, #308] @ () bl #ifndef SKIP_SYSCLK_INIT #if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1) #warning "SKIP_SYSCLK_INIT should be defined to keep system pll (selected to be SEMC source clock in SDK projects) unchanged." #endif /* Init System PLL. */ CLOCK_InitSysPll(&sysPllConfig_BOARD_BootClockRUN); ldr r0, [pc, #304] @ () bl /* Init System pfd0. */ CLOCK_InitSysPfd(kCLOCK_Pfd0, 27); movs r1, #27 movs r0, #0 bl /* Init System pfd1. */ CLOCK_InitSysPfd(kCLOCK_Pfd1, 16); movs r1, #16 movs r0, #1 bl /* Init System pfd2. */ CLOCK_InitSysPfd(kCLOCK_Pfd2, 24); movs r1, #24 movs r0, #2 bl /* Init System pfd3. */ CLOCK_InitSysPfd(kCLOCK_Pfd3, 16); movs r1, #16 movs r0, #3 bl CLOCK_InitUsb1Pfd(kCLOCK_Pfd2, 17); /* Init Usb1 pfd3. */ CLOCK_InitUsb1Pfd(kCLOCK_Pfd3, 19); #endif /* DeInit Audio PLL. */ CLOCK_DeinitAudioPll(); bl mov.w r3, #65536 @ 0x10000 str r3, [r4, #116] @ 0x74 /* Bypass Audio PLL. */ CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllAudio, 1); /* Set divider for Audio PLL. */ CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_LSB_MASK; ldr.w r3, [r4, #368] @ 0x170 bic.w r3, r3, #32768 @ 0x8000 str.w r3, [r4, #368] @ 0x170 CCM_ANALOG->MISC2 &= ~CCM_ANALOG_MISC2_AUDIO_DIV_MSB_MASK; ldr.w r3, [r4, #368] @ 0x170 bic.w r3, r3, #8388608 @ 0x800000 str.w r3, [r4, #368] @ 0x170 /* Enable Audio PLL output. */ CCM_ANALOG->PLL_AUDIO |= CCM_ANALOG_PLL_AUDIO_ENABLE_MASK; ldr r3, [r4, #112] @ 0x70 orr.w r3, r3, #8192 @ 0x2000 str r3, [r4, #112] @ 0x70 /* Init Video PLL. */ uint32_t pllVideo; /* Disable Video PLL output before initial Video PLL. */ CCM_ANALOG->PLL_VIDEO &= ~CCM_ANALOG_PLL_VIDEO_ENABLE_MASK; ldr.w r3, [r4, #160] @ 0xa0 bic.w r3, r3, #8192 @ 0x2000 str.w r3, [r4, #160] @ 0xa0 /* Bypass PLL first */ CCM_ANALOG->PLL_VIDEO = (CCM_ANALOG->PLL_VIDEO & (~CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK)) | ldr.w r3, [r4, #160] @ 0xa0 b.n nop .word 0x200020f4 .word 0x400d8000 .word 0x200020f0 .word 0x016e3600 .word 0x400fc000 .word 0x80006c18 .word 0x14003914 .word 0x40080000 .word 0x0400ea14 .word 0x80006814 .word 0x4000e010 .word 0x8000fb14 .word 0x8007e01c .word 0x8000eb24 .word 0x8000301c .word 0x8000f024 .word 0x8000311c .word 0x80002714 .word 0x80002614 .word 0x8000fa18 .word 0x80006418 .word 0x80007924 .word 0x80006e18 .word 0x8000e628 .word 0x8007e028 .word 0x80006a1c .word 0x8000e62c .word 0x8007e02c .word 0x80006c1c .word 0x8000f628 .word 0x8007f028 .word 0x80006e1c .word 0x8007f338 .word 0x80003238 .word 0x8007e220 .word 0x80006820 .word 0x8007e024 .word 0x80002624 .word 0x8000ec38 .word 0x8000f718 .word 0x8000ef38 .word 0x8000f930 .word 0x8000f630 .word 0x80007430 .word 0x8000ec30 .word 0x8000e930 .word 0x80006730 .word 0x8000e928 .word 0x8000f928 .word 0x80007320 .word 0x8000200c .word 0x60008fc4 .word 0x60008fb0 bic.w r3, r3, #114688 @ 0x1c000 CCM_ANALOG_PLL_VIDEO_BYPASS_MASK | CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC(0); orr.w r3, r3, #65536 @ 0x10000 CCM_ANALOG->PLL_VIDEO = (CCM_ANALOG->PLL_VIDEO & (~CCM_ANALOG_PLL_VIDEO_BYPASS_CLK_SRC_MASK)) | str.w r3, [r4, #160] @ 0xa0 CCM_ANALOG->PLL_VIDEO_NUM = CCM_ANALOG_PLL_VIDEO_NUM_A(0); movs r3, #0 str.w r3, [r4, #176] @ 0xb0 CCM_ANALOG->PLL_VIDEO_DENOM = CCM_ANALOG_PLL_VIDEO_DENOM_B(1); movs r3, #1 str.w r3, [r4, #192] @ 0xc0 pllVideo = (CCM_ANALOG->PLL_VIDEO & (~(CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK | CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK))) | ldr.w r3, [r4, #160] @ 0xa0 CCM_ANALOG_PLL_VIDEO_ENABLE_MASK |CCM_ANALOG_PLL_VIDEO_DIV_SELECT(31); pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1); CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & (~CCM_ANALOG_MISC2_VIDEO_DIV_MASK)) | CCM_ANALOG_MISC2_VIDEO_DIV(3); ldr.w r2, [r4, #368] @ 0x170 pllVideo = (CCM_ANALOG->PLL_VIDEO & (~(CCM_ANALOG_PLL_VIDEO_DIV_SELECT_MASK | CCM_ANALOG_PLL_VIDEO_POWERDOWN_MASK))) | bic.w r3, r3, #12352 @ 0x3040 bic.w r3, r3, #63 @ 0x3f pllVideo |= CCM_ANALOG_PLL_VIDEO_POST_DIV_SELECT(1); orr.w r3, r3, #532480 @ 0x82000 orr.w r3, r3, #31 CCM_ANALOG->MISC2 = (CCM_ANALOG->MISC2 & (~CCM_ANALOG_MISC2_VIDEO_DIV_MASK)) | CCM_ANALOG_MISC2_VIDEO_DIV(3); orr.w r2, r2, #3221225472 @ 0xc0000000 str.w r2, [r4, #368] @ 0x170 CCM_ANALOG->PLL_VIDEO = pllVideo; str.w r3, [r4, #160] @ 0xa0 while ((CCM_ANALOG->PLL_VIDEO & CCM_ANALOG_PLL_VIDEO_LOCK_MASK) == 0) ldr.w r3, [r4, #160] @ 0xa0 cmp r3, #0 bge.n } else { CCM_ANALOG_TUPLE_REG_OFF(base, pll, 8U) = 1UL << CCM_ANALOG_PLL_BYPASS_SHIFT; mov.w r5, #65536 @ 0x10000 str.w r5, [r4, #168] @ 0xa8 { } /* Disable bypass for Video PLL. */ CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllVideo, 0); /* DeInit Enet PLL. */ CLOCK_DeinitEnetPll(); bl CCM_ANALOG_TUPLE_REG_OFF(base, pll, 4U) = 1UL << CCM_ANALOG_PLL_BYPASS_SHIFT; str.w r5, [r4, #228] @ 0xe4 /* Bypass Enet PLL. */ CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllEnet, 1); /* Set Enet output divider. */ CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_DIV_SELECT(1); ldr.w r3, [r4, #224] @ 0xe0 bic.w r3, r3, #3 orr.w r3, r3, #1 str.w r3, [r4, #224] @ 0xe0 /* Enable Enet output. */ CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENABLE_MASK; ldr.w r3, [r4, #224] @ 0xe0 orr.w r3, r3, #8192 @ 0x2000 str.w r3, [r4, #224] @ 0xe0 /* Set Enet2 output divider. */ CCM_ANALOG->PLL_ENET = (CCM_ANALOG->PLL_ENET & (~CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT_MASK)) | CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT(0); ldr.w r3, [r4, #224] @ 0xe0 bic.w r3, r3, #12 str.w r3, [r4, #224] @ 0xe0 /* Enable Enet2 output. */ CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET2_REF_EN_MASK; ldr.w r3, [r4, #224] @ 0xe0 orr.w r3, r3, #1048576 @ 0x100000 str.w r3, [r4, #224] @ 0xe0 /* Enable Enet25M output. */ CCM_ANALOG->PLL_ENET |= CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN_MASK; ldr.w r3, [r4, #224] @ 0xe0 orr.w r3, r3, #2097152 @ 0x200000 str.w r3, [r4, #224] @ 0xe0 /* DeInit Usb2 PLL. */ CLOCK_DeinitUsb2Pll(); bl str r5, [r4, #36] @ 0x24 /* Bypass Usb2 PLL. */ CLOCK_SetPllBypass(CCM_ANALOG, kCLOCK_PllUsb2, 1); /* Enable Usb2 PLL output. */ CCM_ANALOG->PLL_USB2 |= CCM_ANALOG_PLL_USB2_ENABLE_MASK; ldr r3, [r4, #32] /* Set preperiph clock source. */ CLOCK_SetMux(kCLOCK_PrePeriphMux, 3); ldr r0, [pc, #208] @ () CCM_ANALOG->PLL_USB2 |= CCM_ANALOG_PLL_USB2_ENABLE_MASK; orr.w r3, r3, #8192 @ 0x2000 str r3, [r4, #32] CLOCK_SetMux(kCLOCK_PrePeriphMux, 3); movs r1, #3 bl /* Set periph clock source. */ CLOCK_SetMux(kCLOCK_PeriphMux, 0); ldr r0, [pc, #200] @ () movs r1, #0 bl /* Set periph clock2 clock source. */ CLOCK_SetMux(kCLOCK_PeriphClk2Mux, 0); ldr r0, [pc, #196] @ () movs r1, #0 bl /* Set per clock source. */ CLOCK_SetMux(kCLOCK_PerclkMux, 0); ldr r0, [pc, #192] @ () movs r1, #0 bl /* Set lvds1 clock source. */ CCM_ANALOG->MISC1 = (CCM_ANALOG->MISC1 & (~CCM_ANALOG_MISC1_LVDS1_CLK_SEL_MASK)) | CCM_ANALOG_MISC1_LVDS1_CLK_SEL(0); ldr.w r3, [r4, #352] @ 0x160 bic.w r3, r3, #31 str.w r3, [r4, #352] @ 0x160 /* Set clock out1 divider. */ CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_DIV_MASK)) | CCM_CCOSR_CLKO1_DIV(0); ldr r3, [pc, #176] @ () ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #112 @ 0x70 str r2, [r3, #96] @ 0x60 /* Set clock out1 source. */ CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO1_SEL_MASK)) | CCM_CCOSR_CLKO1_SEL(1); ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #15 orr.w r2, r2, #1 str r2, [r3, #96] @ 0x60 /* Set clock out2 divider. */ CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_DIV_MASK)) | CCM_CCOSR_CLKO2_DIV(0); ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #14680064 @ 0xe00000 str r2, [r3, #96] @ 0x60 /* Set clock out2 source. */ CCM->CCOSR = (CCM->CCOSR & (~CCM_CCOSR_CLKO2_SEL_MASK)) | CCM_CCOSR_CLKO2_SEL(18); ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #2031616 @ 0x1f0000 orr.w r2, r2, #1179648 @ 0x120000 str r2, [r3, #96] @ 0x60 /* Set clock out1 drives clock out1. */ CCM->CCOSR &= ~CCM_CCOSR_CLK_OUT_SEL_MASK; ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #256 @ 0x100 str r2, [r3, #96] @ 0x60 /* Disable clock out1. */ CCM->CCOSR &= ~CCM_CCOSR_CLKO1_EN_MASK; ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #128 @ 0x80 str r2, [r3, #96] @ 0x60 /* Disable clock out2. */ CCM->CCOSR &= ~CCM_CCOSR_CLKO2_EN_MASK; ldr r2, [r3, #96] @ 0x60 bic.w r2, r2, #16777216 @ 0x1000000 str r2, [r3, #96] @ 0x60 gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_HIGHBITMASK << (uint32_t)mclk); base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_HIGHBITMASK) << (uint32_t)mclk) | gpr; } else { gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_LOWBITMASK << (uint32_t)mclk); sub.w r3, r3, #327680 @ 0x50000 ldr r2, [r3, #4] bic.w r2, r2, #7 base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_LOWBITMASK) << (uint32_t)mclk) | gpr; str r2, [r3, #4] gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_LOWBITMASK << (uint32_t)mclk); ldr r2, [r3, #4] bic.w r2, r2, #56 @ 0x38 base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_LOWBITMASK) << (uint32_t)mclk) | gpr; str r2, [r3, #4] gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_HIGHBITMASK << (uint32_t)mclk); ldr r2, [r3, #4] bic.w r2, r2, #192 @ 0xc0 base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_HIGHBITMASK) << (uint32_t)mclk) | gpr; str r2, [r3, #4] gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_HIGHBITMASK << (uint32_t)mclk); ldr r2, [r3, #4] bic.w r2, r2, #768 @ 0x300 base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_HIGHBITMASK) << (uint32_t)mclk) | gpr; str r2, [r3, #4] gpr = base->GPR1 & ~((uint32_t)IOMUXC_GPR_SAIMCLK_HIGHBITMASK << (uint32_t)mclk); ldr r2, [r3, #4] bic.w r2, r2, #3072 @ 0xc00 base->GPR1 = (((uint32_t)clkSrc & IOMUXC_GPR_SAIMCLK_HIGHBITMASK) << (uint32_t)mclk) | gpr; str r2, [r3, #4] * @param divider The divider ratio control for mclk from hmclk. mclk freq = 1 /(divider + 1) * hmclk freq. */ static inline void IOMUXC_MQSConfig(IOMUXC_GPR_Type *base, iomuxc_mqs_pwm_oversample_rate_t rate, uint8_t divider) { uint32_t gpr = base->GPR2 & ~(IOMUXC_GPR_GPR2_MQS_OVERSAMPLE_MASK | IOMUXC_GPR_GPR2_MQS_CLK_DIV_MASK); ldr r2, [r3, #8] bic.w r2, r2, #83361792 @ 0x4f80000 bic.w r2, r2, #458752 @ 0x70000 base->GPR2 = gpr | IOMUXC_GPR_GPR2_MQS_OVERSAMPLE(rate) | IOMUXC_GPR_GPR2_MQS_CLK_DIV(divider); str r2, [r3, #8] base->GPR1 &= ~mode; ldr r2, [r3, #4] bic.w r2, r2, #8192 @ 0x2000 str r2, [r3, #4] ldr r2, [r3, #4] bic.w r2, r2, #16384 @ 0x4000 str r2, [r3, #4] IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET2RefClkMode, false); #else IOMUXC_EnableMode(IOMUXC_GPR, IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK, false); #endif /* Set GPT1 High frequency reference clock source. */ IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT1_MASK; ldr r2, [r3, #20] bic.w r2, r2, #268435456 @ 0x10000000 str r2, [r3, #20] /* Set GPT2 High frequency reference clock source. */ IOMUXC_GPR->GPR5 &= ~IOMUXC_GPR_GPR5_VREF_1M_CLK_GPT2_MASK; ldr r2, [r3, #20] bic.w r2, r2, #536870912 @ 0x20000000 str r2, [r3, #20] /* Set SystemCoreClock variable. */ SystemCoreClock = BOARD_BOOTCLOCKRUN_CORE_CLOCK; ldr r3, [pc, #24] @ () ldr r2, [pc, #28] @ () str r2, [r3, #0] } pop {r3, r4, r5, pc} .word 0x80007218 .word 0x14003914 .word 0x80006c18 .word 0x8000261c .word 0x400fc000 .word 0x20000c2c .word 0x23c34600 : BOARD_BootClockRUN(); b.w : __ASM volatile ("cpsid i" : : : "memory"); cpsid i __disable_irq(); // Switch to final VTOR as quickly as possible to have fault handlers set up // (e.g. HardFault) for easier debugging. When encountering a fault without a // usable VTOR table, the MCU will raise another fault and end up in lockup. SCB->VTOR = (uint32_t)&_vectors; ldr r3, [pc, #68] @ () ldr r2, [pc, #68] @ () str r2, [r3, #8] IOMUXC_GPR->GPR17 = 0xaaaaaaaa; ldr r3, [pc, #68] @ () mov.w r2, #2863311530 @ 0xaaaaaaaa str r2, [r3, #68] @ 0x44 __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy __DSB(); __ISB(); IOMUXC_GPR->GPR16 &= ~IOMUXC_GPR_GPR16_INIT_ITCM_EN_MASK; ldr r2, [r3, #64] @ 0x40 bic.w r2, r2, #1 str r2, [r3, #64] @ 0x40 IOMUXC_GPR->GPR16 |= ldr r2, [r3, #64] @ 0x40 orr.w r2, r2, #6 str r2, [r3, #64] @ 0x40 __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy IOMUXC_GPR_GPR16_INIT_ITCM_EN(0); __DSB(); __ISB(); uint32_t current_gpr14 = IOMUXC_GPR->GPR14; ldr r2, [r3, #56] @ 0x38 current_gpr14 &= ~IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ_MASK; current_gpr14 |= IOMUXC_GPR_GPR14_CM7_CFGDTCMSZ(10); current_gpr14 &= ~IOMUXC_GPR_GPR14_CM7_CFGITCMSZ_MASK; bic.w r2, r2, #16711680 @ 0xff0000 orr.w r2, r2, #10485760 @ 0xa00000 current_gpr14 |= IOMUXC_GPR_GPR14_CM7_CFGITCMSZ(0); IOMUXC_GPR->GPR14 = current_gpr14; str r2, [r3, #56] @ 0x38 __ASM volatile ("dsb 0xF":::"memory"); dsb sy __ASM volatile ("isb 0xF":::"memory"); isb sy __DSB(); __ISB(); Reset_Handler(); b.w .word 0xe000ed00 .word 0x60001400 .word 0x400ac000 : #define SIZE_4G (SCB_MPU_RASR_SIZE(31) | SCB_MPU_RASR_ENABLE) #define REGION(n) (SCB_MPU_RBAR_REGION(n) | SCB_MPU_RBAR_VALID) void MIMXRT1062_MPU_init(void) { MPU->CTRL = 0; // turn off MPU ldr r3, [pc, #108] @ () movs r2, #0 str.w r2, [r3, #148] @ 0x94 uint32_t i = 0; MPU->RBAR = 0x00000000 | REGION(i++); //https://developer.arm.com/docs/146793866/10/why-does-the-cortex-m7-initiate-axim-read-accesses-to-memory-addresses-that-do-not-fall-under-a-defined-mpu-region movs r2, #16 str.w r2, [r3, #156] @ 0x9c MPU->RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_4G; ldr r2, [pc, #100] @ () str.w r2, [r3, #160] @ 0xa0 /* MPU->RBAR = 0x00000000 | REGION(i++); // ITCM */ /* MPU->RASR = MEM_NOCACHE | READWRITE | SIZE_512K; */ // TODO: trap regions should be created last, because the hardware gives // priority to the higher number ones. MPU->RBAR = 0x00000000 | REGION(i++); // trap NULL pointer deref movs r2, #17 str.w r2, [r3, #156] @ 0x9c MPU->RASR = DEV_NOCACHE | NOACCESS | SIZE_32B; ldr r2, [pc, #92] @ () str.w r2, [r3, #160] @ 0xa0 MPU->RBAR = 0x00200000 | REGION(i++); // Boot ROM ldr r2, [pc, #88] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = MEM_CACHE_WT | READONLY | SIZE_128K; ldr r2, [pc, #88] @ () str.w r2, [r3, #160] @ 0xa0 MPU->RBAR = 0x20000000 | REGION(i++); // DTCM ldr r2, [pc, #84] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = MEM_NOCACHE | READWRITE | NOEXEC | SIZE_512K; ldr r2, [pc, #84] @ () str.w r2, [r3, #160] @ 0xa0 // teensy4/startup.c sets up a region on the stack to detect stack overflow. // ChibiOS, at the time of writing, does not. // MPU->RBAR = ((uint32_t)&_ebss) | REGION(i++); // trap stack overflow // MPU->RASR = SCB_MPU_RASR_TEX(0) | NOACCESS | NOEXEC | SIZE_32B; MPU->RBAR = 0x20200000 | REGION(i++); // RAM (AXI bus) ldr r2, [pc, #80] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_1M; ldr r2, [pc, #80] @ () str.w r2, [r3, #160] @ 0xa0 MPU->RBAR = 0x40000000 | REGION(i++); // Peripherals ldr r2, [pc, #76] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = DEV_NOCACHE | READWRITE | NOEXEC | SIZE_64M; ldr r2, [pc, #76] @ () str.w r2, [r3, #160] @ 0xa0 MPU->RBAR = 0x60000000 | REGION(i++); // QSPI Flash ldr r2, [pc, #72] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = MEM_CACHE_WBWA | READONLY | SIZE_16M; ldr r2, [pc, #72] @ () str.w r2, [r3, #160] @ 0xa0 MPU->RBAR = 0x70000000 | REGION(i++); // FlexSPI2 ldr r2, [pc, #68] @ () str.w r2, [r3, #156] @ 0x9c MPU->RASR = MEM_CACHE_WBWA | READWRITE | NOEXEC | SIZE_16M; ldr r2, [pc, #68] @ () str.w r2, [r3, #160] @ 0xa0 // TODO: protect access to power supply config MPU->CTRL = SCB_MPU_CTRL_ENABLE; movs r2, #1 str.w r2, [r3, #148] @ 0x94 } bx lr .word 0xe000ed00 .word 0x1000003f .word 0x00100009 .word 0x00200012 .word 0x07020021 .word 0x20000013 .word 0x13080025 .word 0x20200014 .word 0x130b0027 .word 0x40000015 .word 0x13100033 .word 0x60000016 .word 0x070b002f .word 0x70000017 .word 0x130b002f <_pal_lld_readpad>: * * @notapi */ uint8_t _pal_lld_readpad(ioportid_t port, uint8_t pad) { return (port->DR & ((uint32_t) 1 << bit_by_index[pad])) ? PAL_HIGH : PAL_LOW; ldr r3, [pc, #12] @ (<_pal_lld_readpad+0x10>) ldr r0, [r0, #0] ldrb r3, [r3, r1] lsrs r0, r3 } and.w r0, r0, #1 bx lr nop .word 0x20000c9e <_pal_lld_writepad>: */ void _pal_lld_writepad(ioportid_t port, uint8_t pad, uint8_t bit) { if (bit == PAL_HIGH) port->DR_SET = ((uint32_t) 1 << bit_by_index[pad]); ldr r3, [pc, #20] @ (<_pal_lld_writepad+0x18>) ldrb r1, [r3, r1] movs r3, #1 lsls r3, r1 if (bit == PAL_HIGH) cmp r2, #1 port->DR_SET = ((uint32_t) 1 << bit_by_index[pad]); ite eq streq.w r3, [r0, #132] @ 0x84 else port->DR_CLEAR = ((uint32_t) 1 << bit_by_index[pad]); strne.w r3, [r0, #136] @ 0x88 } bx lr nop .word 0x20000c9e <_pal_lld_setpadmode>: * * @notapi */ void _pal_lld_setpadmode(ioportid_t port, uint8_t pad, iomode_t mode) { push {r4, r5, r6, lr} osalDbgAssert(pad < PADS_PER_PORT, "pal_lld_setpadmode() #1, invalid pad"); // see IMXRT1060RM Section 12.4.3 GPIO programming // Interrupt Mask Register (IMR) port->IMR &= ~((uint32_t) 1 << bit_by_index[pad]); ldr r4, [pc, #308] @ (<_pal_lld_setpadmode+0x138>) ldr r3, [r0, #20] ldrb r6, [r4, r1] movs r5, #1 lsls r5, r6 bic.w r3, r3, r5 str r3, [r0, #20] // All GPIOs are on mode ALT5 as per Chapter 10, External Signals and Pin Multiplexing, Table 10-1 const int altMode = 5; switch (mode) { cmp r2, #22 bhi.n <_pal_lld_setpadmode+0x56> tbb [pc, r2] .short 0x730c .word 0x7346360c .word 0x1e1e250c .word 0x1e1e1e1e .word 0x5e561e1e .word 0x7a736c65 .byte 0x81 .byte 0x00 case PAL_MODE_RESET: case PAL_MODE_INPUT: case PAL_MODE_OUTPUT_PUSHPULL: IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #264] @ (<_pal_lld_setpadmode+0x13c>) ldr r5, [pc, #264] @ (<_pal_lld_setpadmode+0x140>) ldrb r3, [r3, r1] adds r3, #4 add.w r3, r5, r3, lsl #2 movs r6, #5 str r6, [r3, #4] PIN_MUX_ALTERNATIVE(altMode); // need to always set PAD_CTL in case the pin was configured as input before IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = ldr r3, [pc, #256] @ (<_pal_lld_setpadmode+0x144>) ldrb r3, [r3, r1] adds r3, #128 @ 0x80 add.w r5, r5, r3, lsl #2 PIN_MUX_ALTERNATIVE(7); break; } // GPIO direction register (GDIR) if (mode == PAL_MODE_OUTPUT_PUSHPULL) { cmp r2, #6 IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = mov.w r3, #48 @ 0x30 str r3, [r5, #4] if (mode == PAL_MODE_OUTPUT_PUSHPULL) { beq.n <_pal_lld_setpadmode+0x12a> port->GDIR |= ((uint32_t) 1 << bit_by_index[pad]); } else { port->GDIR &= ~((uint32_t) 1 << bit_by_index[pad]); ldrb r1, [r4, r1] ldr r3, [r0, #4] movs r2, #1 lsls r2, r1 bic.w r3, r3, r2 b.n <_pal_lld_setpadmode+0x134> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #212] @ (<_pal_lld_setpadmode+0x13c>) ldr r2, [pc, #216] @ (<_pal_lld_setpadmode+0x140>) ldrb r3, [r3, r1] adds r3, #4 add.w r3, r2, r3, lsl #2 movs r5, #5 str r5, [r3, #4] IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = ldr r3, [pc, #204] @ (<_pal_lld_setpadmode+0x144>) ldrb r3, [r3, r1] adds r3, #128 @ 0x80 add.w r2, r2, r3, lsl #2 mov.w r3, #2048 @ 0x800 IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = str r3, [r2, #4] if (mode == PAL_MODE_OUTPUT_PUSHPULL) { b.n <_pal_lld_setpadmode+0x56> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #180] @ (<_pal_lld_setpadmode+0x13c>) ldr r2, [pc, #180] @ (<_pal_lld_setpadmode+0x140>) ldrb r3, [r3, r1] adds r3, #4 add.w r3, r2, r3, lsl #2 movs r5, #5 str r5, [r3, #4] IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = ldr r3, [pc, #172] @ (<_pal_lld_setpadmode+0x144>) ldrb r3, [r3, r1] adds r3, #128 @ 0x80 add.w r2, r2, r3, lsl #2 mov.w r3, #28672 @ 0x7000 b.n <_pal_lld_setpadmode+0x82> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #148] @ (<_pal_lld_setpadmode+0x13c>) ldr r2, [pc, #148] @ (<_pal_lld_setpadmode+0x140>) ldrb r3, [r3, r1] adds r3, #4 add.w r3, r2, r3, lsl #2 movs r5, #5 str r5, [r3, #4] IOMUXC->SW_PAD_CTL_PAD[SW_PAD_CTL_PAD_by_index[pad]] = ldr r3, [pc, #140] @ (<_pal_lld_setpadmode+0x144>) ldrb r3, [r3, r1] adds r3, #128 @ 0x80 add.w r2, r2, r3, lsl #2 mov.w r3, #12288 @ 0x3000 b.n <_pal_lld_setpadmode+0x82> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #116] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #124] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #1 IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = str r2, [r3, #4] if (mode == PAL_MODE_OUTPUT_PUSHPULL) { b.n <_pal_lld_setpadmode+0x56> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #100] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #108] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #2 b.n <_pal_lld_setpadmode+0xd2> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #84] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #92] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #3 b.n <_pal_lld_setpadmode+0xd2> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #72] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #80] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #4 b.n <_pal_lld_setpadmode+0xd2> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #56] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #64] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #5 b.n <_pal_lld_setpadmode+0xd2> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #44] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #52] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #6 b.n <_pal_lld_setpadmode+0xd2> IOMUXC->SW_MUX_CTL_PAD[SW_MUX_CTL_PAD_by_index[pad]] = ldr r3, [pc, #28] @ (<_pal_lld_setpadmode+0x13c>) ldrb r2, [r3, r1] ldr r3, [pc, #36] @ (<_pal_lld_setpadmode+0x148>) lsls r2, r2, #2 add r3, r2 movs r2, #7 b.n <_pal_lld_setpadmode+0xd2> port->GDIR |= ((uint32_t) 1 << bit_by_index[pad]); ldrb r1, [r4, r1] ldr r2, [r0, #4] movs r3, #1 lsls r3, r1 orrs r3, r2 port->GDIR &= ~((uint32_t) 1 << bit_by_index[pad]); str r3, [r0, #4] } } pop {r4, r5, r6, pc} .word 0x20000c9e .word 0x20000c67 .word 0x401f8000 .word 0x20000c30 .word 0x401f8010 <_pal_lld_init>: */ void _pal_lld_init(const PALConfig *config) { (void)config; /* Clocks are already enabled because MIMXRT1062_clock_init() enables GPIO earlier in the boot. */ } bx lr ... : * param bypassXtalOsc Pass in true to bypass the external crystal oscillator. * note This device does not support bypass external crystal oscillator, so * the input parameter should always be false. */ void CLOCK_InitExternalClk(bool bypassXtalOsc) { push {r3, lr} /* This device does not support bypass XTAL OSC. */ assert(!bypassXtalOsc); cbz r0, ldr r3, [pc, #52] @ () ldr r2, [pc, #56] @ () ldr r0, [pc, #56] @ () movs r1, #193 @ 0xc1 bl <__assert_func> CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_XTAL_24M_PWD_MASK; /* Power up */ ldr r3, [pc, #52] @ () mov.w r2, #1073741824 @ 0x40000000 str.w r2, [r3, #344] @ 0x158 while ((XTALOSC24M->LOWPWR_CTRL & XTALOSC24M_LOWPWR_CTRL_XTALOSC_PWRUP_STAT_MASK) == 0U) ldr.w r2, [r3, #624] @ 0x270 lsls r1, r2, #15 bpl.n { } CCM_ANALOG->MISC0_SET = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; /* detect freq */ mov.w r2, #65536 @ 0x10000 str.w r2, [r3, #340] @ 0x154 while ((CCM_ANALOG->MISC0 & CCM_ANALOG_MISC0_OSC_XTALOK_MASK) == 0UL) ldr.w r2, [r3, #336] @ 0x150 lsls r2, r2, #16 bpl.n { } CCM_ANALOG->MISC0_CLR = CCM_ANALOG_MISC0_OSC_XTALOK_EN_MASK; mov.w r2, #65536 @ 0x10000 str.w r2, [r3, #344] @ 0x158 } pop {r3, pc} .word 0x60008ebb .word 0x60008fcc .word 0x60008eca .word 0x400d8000 : * * param osc OSC source to switch to. */ void CLOCK_SwitchOsc(clock_osc_t osc) { if (osc == kCLOCK_RcOsc) ldr r3, [pc, #16] @ () movs r2, #16 cbnz r0, { XTALOSC24M->LOWPWR_CTRL_SET = XTALOSC24M_LOWPWR_CTRL_SET_OSC_SEL_MASK; str.w r2, [r3, #628] @ 0x274 bx lr } else { XTALOSC24M->LOWPWR_CTRL_CLR = XTALOSC24M_LOWPWR_CTRL_CLR_OSC_SEL_MASK; str.w r2, [r3, #632] @ 0x278 } } bx lr nop .word 0x400d8000 : /*! * brief Initialize the RC oscillator 24MHz clock. */ void CLOCK_InitRcOsc24M(void) { XTALOSC24M->LOWPWR_CTRL |= XTALOSC24M_LOWPWR_CTRL_RC_OSC_EN_MASK; ldr r2, [pc, #12] @ () ldr.w r3, [r2, #624] @ 0x270 orr.w r3, r3, #1 str.w r3, [r2, #624] @ 0x270 } bx lr .word 0x400d8000 : * retval false The clock source is invalid to get proper USB HS clock. */ bool CLOCK_EnableUsbhs0Clock(clock_usb_src_t src, uint32_t freq) { uint32_t i; CCM->CCGR6 |= CCM_CCGR6_CG0_MASK; ldr r2, [pc, #64] @ () ldr.w r3, [r2, #128] @ 0x80 orr.w r3, r3, #3 str.w r3, [r2, #128] @ 0x80 USB1->USBCMD |= USBHS_USBCMD_RST_MASK; add.w r2, r2, #1982464 @ 0x1e4000 ldr.w r3, [r2, #320] @ 0x140 orr.w r3, r3, #2 str.w r3, [r2, #320] @ 0x140 ldr r3, [pc, #40] @ () /* Add a delay between RST and RS so make sure there is a DP pullup sequence*/ for (i = 0; i < 400000U; i++) { __ASM("nop"); nop for (i = 0; i < 400000U; i++) subs r3, #1 bne.n } PMU->REG_3P0 = (PMU->REG_3P0 & (~PMU_REG_3P0_OUTPUT_TRG_MASK)) | ldr r2, [pc, #36] @ () ldr.w r3, [r2, #288] @ 0x120 bic.w r3, r3, #7936 @ 0x1f00 bic.w r3, r3, #1 orr.w r3, r3, #5888 @ 0x1700 orr.w r3, r3, #1 str.w r3, [r2, #288] @ 0x120 (PMU_REG_3P0_OUTPUT_TRG(0x17) | PMU_REG_3P0_ENABLE_LINREG_MASK); return true; } movs r0, #1 bx lr .word 0x400fc000 .word 0x00061a80 .word 0x400d8000 : * param config configuration to set to PLL. */ void CLOCK_InitArmPll(const clock_arm_pll_config_t *config) { /* Bypass PLL first */ CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) | ldr r2, [pc, #60] @ () CCM_ANALOG_PLL_ARM_BYPASS_MASK | CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC(config->src); ldrb r3, [r0, #4] CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) | ldr r1, [r2, #0] CCM_ANALOG_PLL_ARM_BYPASS_MASK | CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC(config->src); lsls r3, r3, #14 CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) | bic.w r1, r1, #114688 @ 0x1c000 CCM_ANALOG_PLL_ARM_BYPASS_MASK | CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC(config->src); uxth r3, r3 orrs r3, r1 orr.w r3, r3, #65536 @ 0x10000 CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~CCM_ANALOG_PLL_ARM_BYPASS_CLK_SRC_MASK)) | str r3, [r2, #0] CCM_ANALOG->PLL_ARM = (CCM_ANALOG->PLL_ARM & (~(CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK | CCM_ANALOG_PLL_ARM_POWERDOWN_MASK))) | ldr r1, [r2, #0] CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider); ldr r3, [r0, #0] (CCM_ANALOG->PLL_ARM & (~(CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK | CCM_ANALOG_PLL_ARM_POWERDOWN_MASK))) | bic.w r1, r1, #12352 @ 0x3040 CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider); and.w r3, r3, #127 @ 0x7f (CCM_ANALOG->PLL_ARM & (~(CCM_ANALOG_PLL_ARM_DIV_SELECT_MASK | CCM_ANALOG_PLL_ARM_POWERDOWN_MASK))) | bic.w r1, r1, #63 @ 0x3f CCM_ANALOG_PLL_ARM_ENABLE_MASK | CCM_ANALOG_PLL_ARM_DIV_SELECT(config->loopDivider); orrs r3, r1 orr.w r3, r3, #8192 @ 0x2000 CCM_ANALOG->PLL_ARM = str r3, [r2, #0] while ((CCM_ANALOG->PLL_ARM & CCM_ANALOG_PLL_ARM_LOCK_MASK) == 0UL) ldr r3, [r2, #0] cmp r3, #0 bge.n { } /* Disable Bypass */ CCM_ANALOG->PLL_ARM &= ~CCM_ANALOG_PLL_ARM_BYPASS_MASK; ldr r3, [r2, #0] bic.w r3, r3, #65536 @ 0x10000 str r3, [r2, #0] } bx lr nop .word 0x400d8000 : * param config Configuration to set to PLL. */ void CLOCK_InitSysPll(const clock_sys_pll_config_t *config) { /* Bypass PLL first */ CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | ldr r3, [pc, #96] @ () CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src); ldrb r2, [r0, #12] CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | ldr r1, [r3, #48] @ 0x30 CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src); lsls r2, r2, #14 CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | bic.w r1, r1, #114688 @ 0x1c000 CCM_ANALOG_PLL_SYS_BYPASS_MASK | CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC(config->src); uxth r2, r2 orrs r2, r1 orr.w r2, r2, #65536 @ 0x10000 CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~CCM_ANALOG_PLL_SYS_BYPASS_CLK_SRC_MASK)) | str r2, [r3, #48] @ 0x30 CCM_ANALOG->PLL_SYS = (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) | ldr r1, [r3, #48] @ 0x30 CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider); ldrb r2, [r0, #0] (CCM_ANALOG->PLL_SYS & (~(CCM_ANALOG_PLL_SYS_DIV_SELECT_MASK | CCM_ANALOG_PLL_SYS_POWERDOWN_MASK))) | bic.w r1, r1, #12288 @ 0x3000 bic.w r1, r1, #1 CCM_ANALOG_PLL_SYS_ENABLE_MASK | CCM_ANALOG_PLL_SYS_DIV_SELECT(config->loopDivider); and.w r2, r2, #1 orrs r2, r1 orr.w r2, r2, #8192 @ 0x2000 CCM_ANALOG->PLL_SYS = str r2, [r3, #48] @ 0x30 /* Initialize the fractional mode */ CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator); ldr r2, [r0, #4] CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator); /* Initialize the spread spectrum mode */ CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) | CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) | CCM_ANALOG_PLL_SYS_SS_STOP(config->ss_stop); ldrh r1, [r0, #14] CCM_ANALOG->PLL_SYS_NUM = CCM_ANALOG_PLL_SYS_NUM_A(config->numerator); bic.w r2, r2, #3221225472 @ 0xc0000000 str r2, [r3, #80] @ 0x50 CCM_ANALOG->PLL_SYS_DENOM = CCM_ANALOG_PLL_SYS_DENOM_B(config->denominator); ldr r2, [r0, #8] bic.w r2, r2, #3221225472 @ 0xc0000000 str r2, [r3, #96] @ 0x60 CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) | ldrh r2, [r0, #18] ubfx r2, r2, #0, #15 CCM_ANALOG_PLL_SYS_SS_ENABLE(config->ss_enable) | orr.w r2, r2, r1, lsl #16 ldrb r1, [r0, #16] lsls r1, r1, #15 uxth r1, r1 orrs r2, r1 CCM_ANALOG->PLL_SYS_SS = CCM_ANALOG_PLL_SYS_SS_STEP(config->ss_step) | str r2, [r3, #64] @ 0x40 while ((CCM_ANALOG->PLL_SYS & CCM_ANALOG_PLL_SYS_LOCK_MASK) == 0UL) ldr r2, [r3, #48] @ 0x30 cmp r2, #0 bge.n { } /* Disable Bypass */ CCM_ANALOG->PLL_SYS &= ~CCM_ANALOG_PLL_SYS_BYPASS_MASK; ldr r2, [r3, #48] @ 0x30 bic.w r2, r2, #65536 @ 0x10000 str r2, [r3, #48] @ 0x30 } bx lr .word 0x400d8000 : * param config Configuration to set to PLL. */ void CLOCK_InitUsb1Pll(const clock_usb_pll_config_t *config) { /* Bypass PLL first */ CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | ldr r2, [pc, #60] @ () CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src); ldrb r3, [r0, #1] CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | ldr r1, [r2, #16] CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src); lsls r3, r3, #14 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | bic.w r1, r1, #114688 @ 0x1c000 CCM_ANALOG_PLL_USB1_BYPASS_MASK | CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC(config->src); uxth r3, r3 orrs r3, r1 orr.w r3, r3, #65536 @ 0x10000 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_BYPASS_CLK_SRC_MASK)) | str r3, [r2, #16] CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) | ldr r1, [r2, #16] CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider); ldrb r3, [r0, #0] CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | bic.w r1, r1, #12352 @ 0x3040 CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider); lsls r3, r3, #1 and.w r3, r3, #2 CCM_ANALOG_PLL_USB1_ENABLE_MASK | CCM_ANALOG_PLL_USB1_POWER_MASK | bic.w r1, r1, #2 CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK | CCM_ANALOG_PLL_USB1_DIV_SELECT(config->loopDivider); orrs r3, r1 orr.w r3, r3, #12352 @ 0x3040 CCM_ANALOG->PLL_USB1 = (CCM_ANALOG->PLL_USB1 & (~CCM_ANALOG_PLL_USB1_DIV_SELECT_MASK)) | str r3, [r2, #16] while ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_LOCK_MASK) == 0UL) ldr r3, [r2, #16] cmp r3, #0 bge.n { } /* Disable Bypass */ CCM_ANALOG->PLL_USB1 &= ~CCM_ANALOG_PLL_USB1_BYPASS_MASK; ldr r3, [r2, #16] bic.w r3, r3, #65536 @ 0x10000 str r3, [r2, #16] } bx lr .word 0x400d8000 : { push {r0, r1, r2, lr} const clock_usb_pll_config_t g_ccmConfigUsbPll = {.loopDivider = 0U}; movs r3, #0 strh.w r3, [sp, #4] if ((CCM_ANALOG->PLL_USB1 & CCM_ANALOG_PLL_USB1_ENABLE_MASK) != 0U) ldr r3, [pc, #60] @ () ldr r2, [r3, #16] lsls r2, r2, #18 bpl.n CCM_ANALOG->PLL_USB1 |= CCM_ANALOG_PLL_USB1_EN_USB_CLKS_MASK; ldr r2, [r3, #16] orr.w r2, r2, #64 @ 0x40 str r2, [r3, #16] USBPHY1->CTRL &= ~USBPHY_CTRL_SFTRST_MASK; /* release PHY from reset */ ldr r3, [pc, #48] @ () ldr r2, [r3, #48] @ 0x30 bic.w r2, r2, #2147483648 @ 0x80000000 str r2, [r3, #48] @ 0x30 USBPHY1->CTRL &= ~USBPHY_CTRL_CLKGATE_MASK; ldr r2, [r3, #48] @ 0x30 bic.w r2, r2, #1073741824 @ 0x40000000 str r2, [r3, #48] @ 0x30 USBPHY1->PWD = 0; movs r2, #0 str r2, [r3, #0] USBPHY1->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | ldr r2, [r3, #48] @ 0x30 } movs r0, #1 USBPHY1->CTRL |= USBPHY_CTRL_ENAUTOCLR_PHY_PWD_MASK | USBPHY_CTRL_ENAUTOCLR_CLKGATE_MASK | orr.w r2, r2, #1622016 @ 0x18c000 str r2, [r3, #48] @ 0x30 } add sp, #12 ldr.w pc, [sp], #4 CLOCK_InitUsb1Pll(&g_ccmConfigUsbPll); add r0, sp, #4 bl b.n nop .word 0x400d8000 .word 0x400d9000 : /*! * brief Deinitialize the USB2 PLL. */ void CLOCK_DeinitUsb2Pll(void) { CCM_ANALOG->PLL_USB2 = 0U; ldr r3, [pc, #4] @ () movs r2, #0 str r2, [r3, #32] } bx lr .word 0x400d8000 : /*! * brief De-initialize the Audio PLL. */ void CLOCK_DeinitAudioPll(void) { CCM_ANALOG->PLL_AUDIO = (uint32_t)CCM_ANALOG_PLL_AUDIO_POWERDOWN_MASK; ldr r3, [pc, #8] @ () mov.w r2, #4096 @ 0x1000 str r2, [r3, #112] @ 0x70 } bx lr nop .word 0x400d8000 : * * This function disables the ENET PLL. */ void CLOCK_DeinitEnetPll(void) { CCM_ANALOG->PLL_ENET = CCM_ANALOG_PLL_ENET_POWERDOWN_MASK; ldr r3, [pc, #8] @ () mov.w r2, #4096 @ 0x1000 str.w r2, [r3, #224] @ 0xe0 } bx lr .word 0x400d8000 : * param pfd Which PFD clock to enable. * param pfdFrac The PFD FRAC value. * note It is recommended that PFD settings are kept between 12-35. */ void CLOCK_InitSysPfd(clock_pfd_t pfd, uint8_t pfdFrac) { push {r4, lr} uint32_t pfdIndex = (uint32_t)pfd; uint32_t pfd528; pfd528 = CCM_ANALOG->PFD_528 & ldr r4, [pc, #40] @ () ~(((uint32_t)((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK | CCM_ANALOG_PFD_528_PFD0_FRAC_MASK) << (8UL * pfdIndex))); lsls r0, r0, #3 pfd528 = CCM_ANALOG->PFD_528 & ldr.w r2, [r4, #256] @ 0x100 << (8UL * pfdIndex))); movs r3, #191 @ 0xbf lsls r3, r0 pfd528 = CCM_ANALOG->PFD_528 & bic.w r2, r2, r3 /* Disable the clock output first. */ CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); /* Set the new value and enable output. */ CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); and.w r1, r1, #63 @ 0x3f CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); movs r3, #128 @ 0x80 lsls r3, r0 CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); lsls r1, r0 CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); orrs r3, r2 CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); orrs r1, r2 CCM_ANALOG->PFD_528 = pfd528 | ((uint32_t)CCM_ANALOG_PFD_528_PFD0_CLKGATE_MASK << (8UL * pfdIndex)); str.w r3, [r4, #256] @ 0x100 CCM_ANALOG->PFD_528 = pfd528 | (CCM_ANALOG_PFD_528_PFD0_FRAC(pfdFrac) << (8UL * pfdIndex)); str.w r1, [r4, #256] @ 0x100 } pop {r4, pc} nop .word 0x400d8000 : * @brief System Timer vector. * @details This interrupt is used for system tick in periodic mode. * * @isr */ OSAL_IRQ_HANDLER(SysTick_Handler) { push {r3, lr} __ASM volatile ("MSR basepri, %0" : : "r" (basePri) : "memory"); movs r3, #48 @ 0x30 msr BASEPRI, r3 chSysTimerHandlerI(); bl movs r3, #0 msr BASEPRI, r3 osalSysLockFromISR(); osalOsTimerHandlerI(); osalSysUnlockFromISR(); OSAL_IRQ_EPILOGUE(); } ldmia.w sp!, {r3, lr} OSAL_IRQ_EPILOGUE(); b.w <__port_irq_epilogue> : we will just need to adjust the SysTick configuration accordingly. Using the faster clock allows users to increase the CH_CFG_ST_FREQUENCY for finer grained tick duration and thereby minimum sleep duration when using chThdSleep: 10μs instead of 100μs. */ SysTick->LOAD = (BOARD_BOOTCLOCKRUN_CORE_CLOCK / OSAL_ST_FREQUENCY) - 1; mov.w r3, #3758153728 @ 0xe000e000 movw r2, #59999 @ 0xea5f str r2, [r3, #20] SysTick->VAL = 0; movs r2, #0 str r2, [r3, #24] SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; movs r2, #7 str r2, [r3, #16] /* IRQ enabled.*/ nvicSetSystemHandlerPriority(HANDLER_SYSTICK, MIMXRT1062_ST_IRQ_PRIORITY); movs r1, #8 movs r0, #11 b.w : (void)eventParam; USBDriver *usbp = &USBD1; printf_debug("usb_device_callback(event=%d)", callbackEvent); switch (callbackEvent) { cmp r1, #2 static usb_status_t usb_device_callback(usb_device_handle handle, uint32_t callbackEvent, void *eventParam) { push {r3, lr} switch (callbackEvent) { beq.n cmp r1, #3 beq.n cmp r1, #1 bne.n case kUSB_DeviceEventBusReset: printf_debug(" bus reset"); _usb_reset(usbp); ldr r0, [pc, #24] @ () bl <_usb_reset> _usb_wakeup(usbp); break; } return kStatus_USB_Success; } movs r0, #0 pop {r3, pc} _usb_suspend(usbp); ldr r0, [pc, #12] @ () bl <_usb_suspend> break; b.n _usb_wakeup(usbp); ldr r0, [pc, #4] @ () bl <_usb_wakeup> break; b.n .word 0x2000210c : /** * Called when the USB transfer completed * */ static usb_status_t device_ep0_control_callback(usb_device_handle handle, push {r4, r5, r6, lr} (void)callbackParam; USBDriver *usbp = &USBD1; printf_debug("device_ep0_control_callback"); const uint8_t ep = 0; const USBEndpointConfig *epc = usbp->epc[ep]; ldr r4, [pc, #128] @ () if (message->isSetup) { ldrb r6, [r0, #8] const USBEndpointConfig *epc = usbp->epc[ep]; ldr r5, [r4, #12] /* Clear receiving in the chibios state machine */ (usbp)->receiving &= ~(1 << ep); (usbp)->transmitting &= ~(1 << ep); memcpy(usbp->setup, message->buffer, message->length); ldr r2, [r0, #4] if (message->isSetup) { cbz r6, (usbp)->transmitting &= ~(1 << ep); ldr r3, [r4, #8] memcpy(usbp->setup, message->buffer, message->length); ldr r1, [r0, #0] (usbp)->transmitting &= ~(1 << ep); bic.w r3, r3, #65537 @ 0x10001 memcpy(usbp->setup, message->buffer, message->length); add.w r0, r4, #116 @ 0x74 (usbp)->transmitting &= ~(1 << ep); str r3, [r4, #8] memcpy(usbp->setup, message->buffer, message->length); bl /* Call SETUP function (ChibiOS core), which prepares * for send or receive and releases the buffer */ if (epc->setup_cb != NULL) { ldr r3, [r5, #4] cbz r3, _usb_isr_invoke_setup_cb(usbp, ep); movs r1, #0 mov r0, r4 blx r3 // -> will call usb_lld_read_setup // -> will call e.g. usb_lld_start_in } return kStatus_USB_Success; movs r0, #0 printf_debug(" invoking in_cb for ep %d", ep); _usb_isr_invoke_in_cb(usbp, ep); } return kStatus_USB_Success; } pop {r4, r5, r6, pc} if (message->length == USB_CANCELLED_TRANSFER_LENGTH) { adds r0, r2, #1 beq.n if (direction == USB_OUT) { cbnz r1, osp->rxcnt = message->length; ldr r3, [r5, #24] str r2, [r3, #4] _usb_isr_invoke_out_cb(usbp, ep); ldrh r3, [r4, #10] bic.w r3, r3, #1 strh r3, [r4, #10] ldr r3, [r5, #12] cbz r3, mov r0, r4 blx r3 movs r3, #48 @ 0x30 msr BASEPRI, r3 ldr r3, [r4, #12] ldr r0, [r3, #24] chThdResumeI(trp, msg); ldr r1, [r0, #4] adds r0, #12 bl movs r3, #0 msr BASEPRI, r3 } b.n _usb_isr_invoke_in_cb(usbp, ep); ldrh r3, [r4, #8] bic.w r3, r3, #1 strh r3, [r4, #8] ldr r3, [r5, #8] cbz r3, mov r1, r6 mov r0, r4 blx r3 movs r3, #48 @ 0x30 msr BASEPRI, r3 ldr r3, [r4, #12] chThdResumeI(trp, msg); movs r1, #0 ldr r0, [r3, #20] b.n return kStatus_USB_InvalidRequest; movs r0, #5 b.n .word 0x2000210c : static usb_status_t device_ep0_control_callback_in(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { mov r0, r1 return device_ep0_control_callback(handle, message, callbackParam, USB_IN); movs r1, #1 b.w : } static usb_status_t device_ep0_control_callback_out(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { mov r0, r1 return device_ep0_control_callback(handle, message, callbackParam, USB_OUT); movs r1, #0 b.w : return device_epN_control_callback(handle, message, callbackParam, USB_OUT); } static usb_status_t device_epN_control_callback_in(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { push {r4, r5, r6, lr} if (message->isSetup) { ldrb r5, [r1, #8] cbnz r5, if (message->length == USB_CANCELLED_TRANSFER_LENGTH) { ldr r3, [r1, #4] adds r3, #1 beq.n const USBEndpointConfig *epc = usbp->epc[ep]; ldr r4, [pc, #68] @ () uxtb r1, r2 adds r6, r1, #2 add.w r3, r4, r6, lsl #2 _usb_isr_invoke_in_cb(usbp, ep); movs r2, #1 const USBEndpointConfig *epc = usbp->epc[ep]; ldr r0, [r3, #4] _usb_isr_invoke_in_cb(usbp, ep); ldrh r3, [r4, #8] lsls r2, r1 bic.w r3, r3, r2 strh r3, [r4, #8] ldr r3, [r0, #8] cbz r3, mov r0, r4 blx r3 movs r3, #48 @ 0x30 msr BASEPRI, r3 add.w r4, r4, r6, lsl #2 movs r1, #0 ldr r3, [r4, #4] ldr r0, [r3, #20] adds r0, #12 bl movs r3, #0 msr BASEPRI, r3 return device_epN_control_callback(handle, message, callbackParam, USB_IN); } mov r0, r5 pop {r4, r5, r6, pc} return kStatus_USB_Error; movs r5, #1 b.n return kStatus_USB_InvalidRequest; movs r5, #5 b.n .word 0x2000210c : void *callbackParam) { push {r4, r5, r6, lr} if (message->isSetup) { ldrb r5, [r1, #8] cbnz r5, if (message->length == USB_CANCELLED_TRANSFER_LENGTH) { ldr r3, [r1, #4] adds r1, r3, #1 beq.n const USBEndpointConfig *epc = usbp->epc[ep]; ldr r4, [pc, #72] @ () uxtb r1, r2 adds r6, r1, #2 add.w r2, r4, r6, lsl #2 ldr r0, [r2, #4] osp->rxcnt = message->length; ldr r2, [r0, #24] str r3, [r2, #4] _usb_isr_invoke_out_cb(usbp, ep); ldrh r3, [r4, #10] movs r2, #1 lsls r2, r1 bic.w r3, r3, r2 strh r3, [r4, #10] ldr r3, [r0, #12] cbz r3, mov r0, r4 blx r3 movs r3, #48 @ 0x30 msr BASEPRI, r3 add.w r4, r4, r6, lsl #2 ldr r3, [r4, #4] ldr r0, [r3, #24] ldr r1, [r0, #4] adds r0, #12 bl movs r3, #0 msr BASEPRI, r3 } mov r0, r5 pop {r4, r5, r6, pc} return kStatus_USB_Error; movs r5, #1 b.n return kStatus_USB_InvalidRequest; movs r5, #5 b.n .word 0x2000210c : usb_device_struct_t *dev_handle = (usb_device_struct_t *)handle; ldr r3, [pc, #44] @ () ldr r0, [r3, #0] status = ehciState->registerBase->USBSTS; ldr r3, [r0, #8] ldr r3, [r3, #4] OSAL_IRQ_HANDLER(MIMXRT1062_USB_OTG1_IRQ_VECTOR) { push {r4, lr} status = ehciState->registerBase->USBSTS; ldr.w r4, [r3, #324] @ 0x144 status &= ehciState->registerBase->USBINTR; ldr.w r3, [r3, #328] @ 0x148 ands r4, r3 USB_DeviceEhciIsrFunction(handle); bl if ((status & USBHS_USBSTS_SRI_MASK)) { lsls r3, r4, #24 bpl.n _usb_isr_invoke_sof_cb(usbp); ldr r0, [pc, #20] @ () ldr r3, [r0, #4] ldr r3, [r3, #12] cbz r3, blx r3 } ldmia.w sp!, {r4, lr} OSAL_IRQ_EPILOGUE(); b.w <__port_irq_epilogue> nop .word 0x20002108 .word 0x2000210c : void usb_lld_init(void) { push {r0, r1, r4, lr} CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); ldr r4, [pc, #56] @ () usbObjectInit(usbp); ldr r0, [pc, #56] @ () bl usb_phy_config_struct_t phyConfig = { movs r2, #3 ldr r1, [pc, #52] @ () add r0, sp, #4 bl CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U); mov r1, r4 movs r0, #0 bl CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U); mov r1, r4 movs r0, #0 bl USB_EhciPhyInit(kUSB_ControllerEhci0, notUsed, &phyConfig); add r2, sp, #4 movs r1, #0 movs r0, #2 bl if (USB_DeviceInit(kUSB_ControllerEhci0, usb_device_callback, &handle) != kStatus_USB_Success) { ldr r2, [pc, #24] @ () ldr r1, [pc, #24] @ () movs r0, #2 bl } add sp, #8 pop {r4, pc} .word 0x1c9c3800 .word 0x2000210c .word 0x60008a04 .word 0x20002108 .word 0x600067d9 : void usb_lld_start(USBDriver *usbp) { push {r3, lr} if (usbp->state != USB_STOP) { ldrb r3, [r0, #0] cmp r3, #1 bne.n if (usbp != &USBD1) { ldr r3, [pc, #24] @ () cmp r0, r3 bne.n USB_DeviceRun(handle); ldr r3, [pc, #24] @ () ldr r0, [r3, #0] bl } ldmia.w sp!, {r3, lr} nvicEnableVector(USB_OTG1_IRQn, MIMXRT1062_USB_USB1_IRQ_PRIORITY); movs r1, #3 movs r0, #113 @ 0x71 b.w } pop {r3, pc} .word 0x2000210c .word 0x20002108 : void usb_lld_stop(USBDriver *usbp) { push {r3, lr} if (usbp->state == USB_STOP) { ldrb r3, [r0, #0] cmp r3, #1 bne.n if (&USBD1 == usbp) { ldr r3, [pc, #24] @ () cmp r0, r3 bne.n USB_DeviceStop(handle); ldr r3, [pc, #24] @ () ldr r0, [r3, #0] bl } ldmia.w sp!, {r3, lr} nvicDisableVector(USB_OTG1_IRQn); movs r0, #113 @ 0x71 b.w } pop {r3, pc} nop .word 0x2000210c .word 0x20002108 : void usb_lld_reset(USBDriver *usbp) { push {r4, lr} usbp->epc[0] = &ep0config; ldr r3, [pc, #72] @ () status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); ldr r4, [pc, #72] @ () epInitStruct.maxPacketSize = USB_CONTROL_MAX_PACKET_SIZE; ldr r2, [pc, #76] @ () usbp->epc[0] = &ep0config; str r3, [r0, #12] void usb_lld_reset(USBDriver *usbp) { sub sp, #24 epCallback.callbackFn = device_ep0_control_callback_in; ldr r3, [pc, #72] @ () str r3, [sp, #12] epInitStruct.maxPacketSize = USB_CONTROL_MAX_PACKET_SIZE; str r2, [sp, #4] epCallback.callbackParam = NULL; movs r3, #0 status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); ldr r0, [r4, #0] epCallback.callbackParam = NULL; str r3, [sp, #16] status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); add r2, sp, #12 add r1, sp, #4 epInitStruct.zlt = 0; strh.w r3, [sp, #8] status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); bl if (kStatus_USB_Success != status) { cbnz r0, epCallback.callbackFn = device_ep0_control_callback_out; ldr r3, [pc, #52] @ () epCallback.callbackParam = NULL; str r0, [sp, #16] epInitStruct.endpointAddress = epaddr(USB_CONTROL_ENDPOINT, USB_OUT); strb.w r0, [sp, #6] status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); add r2, sp, #12 ldr r0, [r4, #0] epCallback.callbackFn = device_ep0_control_callback_out; str r3, [sp, #12] status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback); add r1, sp, #4 bl if (kStatus_USB_Success != status) { cbz r0, (void)USB_DeviceDeinitEndpoint(handle, epInitStruct.endpointAddress); ldrb.w r1, [sp, #6] ldr r0, [r4, #0] bl } add sp, #24 pop {r4, pc} nop .word 0x60008fe4 .word 0x20002108 .word 0x00800040 .word 0x6000688d .word 0x60006895 : void usb_lld_set_address(USBDriver *usbp) { push {r0, r1, r4, r5, r6, lr} USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); ldr r4, [pc, #84] @ () void usb_lld_set_address(USBDriver *usbp) { mov r5, r0 uint8_t state = 0U; movs r6, #0 USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); ldr r0, [r4, #0] uint8_t state = 0U; strb.w r6, [sp, #7] USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); add.w r2, sp, #7 movs r1, #6 bl if (((uint8_t)kUSB_DeviceStateAddressing != state) && ((uint8_t)kUSB_DeviceStateAddress != state) && ldrb.w r3, [sp, #7] cmp r3, #3 beq.n cmp r3, #2 bhi.n state = (uint8_t)(usbp->address & 0xFF); ldrb.w r3, [r5, #126] @ 0x7e strb.w r3, [sp, #7] error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, &state); add.w r2, sp, #7 movs r1, #7 error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state); ldr r0, [r4, #0] bl } add sp, #8 pop {r4, r5, r6, pc} error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusAddress, NULL); ldr r0, [r4, #0] mov r2, r6 movs r1, #7 bl if (kStatus_USB_Success == error) { cmp r0, #0 bne.n state = (uint8_t)kUSB_DeviceStateAddress; movs r3, #1 strb.w r3, [sp, #7] error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusDeviceState, &state); add.w r2, sp, #7 movs r1, #6 b.n .word 0x20002108 : * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { push {r4, r5, lr} if(ep > MIMXRT1062_USB_ENDPOINTS) cmp r1, #8 void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { sub sp, #28 mov r4, r1 if(ep > MIMXRT1062_USB_ENDPOINTS) bhi.n return; printf_debug("usb_lld_init_endpoint(ep=%d)", ep); const USBEndpointConfig *epc = usbp->epc[ep]; add.w r0, r0, r1, lsl #2 ldr r5, [r0, #12] if (epc->out_state == NULL && epc->in_state == NULL) { ldr r2, [r5, #24] ldr r3, [r5, #20] cbnz r2, cbz r3, usb_device_endpoint_init_struct_t epInitStruct; usb_device_endpoint_callback_struct_t epCallback; usb_status_t status; epCallback.callbackFn = device_epN_control_callback_in; ldr r2, [pc, #96] @ () str r2, [sp, #12] epCallback.callbackParam = (void*)((uint32_t)ep); epInitStruct.transferType = epc->ep_mode; ldr r2, [r5, #0] strb.w r2, [sp, #7] epInitStruct.zlt = 0; movs r2, #0 epCallback.callbackParam = (void*)((uint32_t)ep); str r4, [sp, #16] epInitStruct.zlt = 0; strh.w r2, [sp, #8] epInitStruct.interval = 0; if (epc->in_state != NULL) { cbnz r3, printf_debug("USB_DeviceInitEndpoint() failed: %d", status); return; } } if (epc->out_state != NULL) { ldr r3, [r5, #24] cbnz r3, return; #if MIMXRT1062_USB_USE_USB1 #endif /* MIMXRT1062_USB_USE_USB1 */ } add sp, #28 pop {r4, r5, pc} return ep | (direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); orn r3, r4, #127 @ 0x7f epInitStruct.endpointAddress = epaddr(ep, USB_IN); strb.w r3, [sp, #6] epInitStruct.maxPacketSize = epc->in_maxsize; ldrh r3, [r5, #16] strh.w r3, [sp, #4] if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { ldr r3, [pc, #60] @ () add r2, sp, #12 ldr r0, [r3, #0] add r1, sp, #4 bl cmp r0, #0 beq.n b.n epInitStruct.endpointAddress = epaddr(ep, USB_OUT); strb.w r4, [sp, #6] if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { ldr r4, [pc, #36] @ () epCallback.callbackFn = device_epN_control_callback_out; ldr r3, [pc, #40] @ () str r3, [sp, #12] if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { ldr r0, [r4, #0] epInitStruct.maxPacketSize = epc->out_maxsize; ldrh r3, [r5, #18] strh.w r3, [sp, #4] if ((status = USB_DeviceInitEndpoint(handle, &epInitStruct, &epCallback)) != kStatus_USB_Success) { add r2, sp, #12 add r1, sp, #4 bl cmp r0, #0 beq.n USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); ldr r0, [r4, #0] movs r1, #128 @ 0x80 bl return; b.n .word 0x6000689d .word 0x20002108 .word 0x600068f5 : printf_debug("TODO: usb_lld_disable_endpoints()"); #if MIMXRT1062_USB_USE_USB1 // TODO: find active endpoints and disable // USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress); #endif /* MIMXRT1062_USB_USE_USB1 */ } bx lr ... : * * @notapi */ usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { (void)usbp; if(ep > USB_MAX_ENDPOINTS) cmp r1, #7 usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep) { push {r0, r1, r2, lr} if(ep > USB_MAX_ENDPOINTS) bhi.n if ((status = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus)) != kStatus_USB_Success) { ldr r3, [pc, #44] @ () endpointStatus.endpointAddress = epaddr(ep, direction); strb.w r1, [sp, #4] if ((status = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus)) != kStatus_USB_Success) { ldr r0, [r3, #0] add r2, sp, #4 movs r1, #5 bl cbnz r0, if (endpointStatus.endpointStatus == kUSB_DeviceEndpointStateStalled) { ldrh.w r3, [sp, #6] return epstatus; cmp r3, #1 ite eq moveq r0, #1 movne r0, #2 return EP_STATUS_DISABLED; #if MIMXRT1062_USB_USE_USB1 printf_debug("usb_lld_get_status_out(ep=%d)", ep); return usb_lld_get_status(usbp, ep, USB_OUT); #endif /* MIMXRT1062_USB_USE_USB1 */ } add sp, #12 ldr.w pc, [sp], #4 return epstatus; movs r0, #2 b.n return EP_STATUS_DISABLED; movs r0, #0 b.n nop .word 0x20002108 : * @notapi */ usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { (void)usbp; if(ep > USB_MAX_ENDPOINTS) cmp r1, #7 usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep) { push {r0, r1, r2, lr} if(ep > USB_MAX_ENDPOINTS) bhi.n if ((status = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus)) != kStatus_USB_Success) { ldr r3, [pc, #48] @ () return ep | (direction << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); orn r1, r1, #127 @ 0x7f endpointStatus.endpointAddress = epaddr(ep, direction); strb.w r1, [sp, #4] if ((status = USB_DeviceGetStatus(handle, kUSB_DeviceStatusEndpoint, &endpointStatus)) != kStatus_USB_Success) { ldr r0, [r3, #0] add r2, sp, #4 movs r1, #5 bl cbnz r0, if (endpointStatus.endpointStatus == kUSB_DeviceEndpointStateStalled) { ldrh.w r3, [sp, #6] return epstatus; cmp r3, #1 ite eq moveq r0, #1 movne r0, #2 return EP_STATUS_DISABLED; #if MIMXRT1062_USB_USE_USB1 printf_debug("usb_lld_get_status_in(ep=%d)", ep); return usb_lld_get_status(usbp, ep, USB_IN); #endif /* MIMXRT1062_USB_USE_USB1 */ } add sp, #12 ldr.w pc, [sp], #4 return epstatus; movs r0, #2 b.n return EP_STATUS_DISABLED; movs r0, #0 b.n nop .word 0x20002108 : (void)ep; (void)buf; // We already populated usbp->setup in device_ep0_control_callback(), so no // extra steps are required in this function. } bx lr ... : * @param[in] ep endpoint number * * @notapi */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { const USBEndpointConfig *epc = usbp->epc[ep]; add.w r0, r0, r1, lsl #2 ldr r3, [r0, #12] USBOutEndpointState *osp = epc->out_state; ldr r2, [r3, #24] printf_debug(" usb_lld_start_out(ep=%d) (receive)", ep); if (osp->rxsize > epc->out_maxsize) { ldrh r3, [r3, #18] ldr r0, [r2, #0] cmp r0, r3 osp->rxsize = epc->out_maxsize; } USB_DeviceRecvRequest(handle, epaddr(ep, USB_OUT), osp->rxbuf, osp->rxsize); ldr r0, [pc, #16] @ () osp->rxsize = epc->out_maxsize; it hi strhi r3, [r2, #0] USB_DeviceRecvRequest(handle, epaddr(ep, USB_OUT), osp->rxbuf, osp->rxsize); ldr r3, [r2, #0] ldr r0, [r0, #0] ldr r2, [r2, #8] b.w nop .word 0x20002108 : * * @note Called from ISR and locked zone. * @notapi */ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { const USBEndpointConfig *epc = usbp->epc[ep]; add.w r0, r0, r1, lsl #2 // the NXP SDK: ChibiOS uses const for isp->txbuf (but not for rxbuf, of // course), but the NXP SDK APIs do not use const at all. uint32_t p = (uint32_t)isp->txbuf; uint8_t *buf = (uint8_t*)p; USB_DeviceSendRequest(handle, epaddr(ep, USB_IN), buf, isp->txsize); orr.w r1, r1, #128 @ 0x80 USBInEndpointState *isp = epc->in_state; ldr r3, [r0, #12] USB_DeviceSendRequest(handle, epaddr(ep, USB_IN), buf, isp->txsize); ldr r0, [pc, #12] @ () USBInEndpointState *isp = epc->in_state; ldr r2, [r3, #20] USB_DeviceSendRequest(handle, epaddr(ep, USB_IN), buf, isp->txsize); ldr r0, [r0, #0] ldr r3, [r2, #0] ldr r2, [r2, #8] b.w .word 0x20002108 : void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { (void)usbp; printf_debug("usb_lld_stall_out(ep=%d)", ep); #if MIMXRT1062_USB_USE_USB1 usb_status_t status; if ((status = USB_DeviceStallEndpoint(handle, epaddr(ep, USB_OUT))) != kStatus_USB_Success) { ldr r3, [pc, #4] @ () ldr r0, [r3, #0] b.w .word 0x20002108 : (void)usbp; printf_debug("usb_lld_stall_in(ep=%d)", ep); #if MIMXRT1062_USB_USE_USB1 usb_status_t status; if ((status = USB_DeviceStallEndpoint(handle, epaddr(ep, USB_IN))) != kStatus_USB_Success) { ldr r3, [pc, #8] @ () orr.w r1, r1, #128 @ 0x80 ldr r0, [r3, #0] b.w .word 0x20002108 : void usb_lld_clear_out(USBDriver *usbp, usbep_t ep) { (void)usbp; printf_debug("usb_lld_clear_out(ep=%d)", ep); #if MIMXRT1062_USB_USE_USB1 usb_status_t status; if ((status = USB_DeviceUnstallEndpoint(handle, epaddr(ep, USB_OUT))) != kStatus_USB_Success) { ldr r3, [pc, #4] @ () ldr r0, [r3, #0] b.w .word 0x20002108 : void usb_lld_clear_in(USBDriver *usbp, usbep_t ep) { (void)usbp; printf_debug("usb_lld_clear_in(ep=%d)", ep); #if MIMXRT1062_USB_USE_USB1 usb_status_t status; if ((status = USB_DeviceUnstallEndpoint(handle, epaddr(ep, USB_IN))) != kStatus_USB_Success) { ldr r3, [pc, #8] @ () orr.w r1, r1, #128 @ 0x80 ldr r0, [r3, #0] b.w .word 0x20002108 : static usb_status_t USB_DeviceControl(usb_device_handle handle, usb_device_control_type_t type, void *param) { usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle; usb_status_t status; if (NULL == deviceHandle) cbz r0, { return kStatus_USB_InvalidHandle; } if (NULL != deviceHandle->controllerInterface) ldr r3, [r0, #12] cbz r3, { /* Call the controller control interface. the controllerInterface is initialized in USB_DeviceGetControllerInterface */ status = deviceHandle->controllerInterface->deviceControl(deviceHandle->controllerHandle, type, param); ldr r3, [r3, #20] ldr r0, [r0, #8] bx r3 return kStatus_USB_InvalidHandle; movs r0, #3 bx lr } else { status = kStatus_USB_ControllerNotFound; movs r0, #6 } return status; } bx lr : { stmdb sp!, {r0, r1, r2, r4, r5, r6, r7, r8, r9, lr} mov r5, r1 mov r7, r2 mov r8, r3 if (NULL == deviceHandle) mov r4, r0 cbz r0, if (NULL != deviceHandle->controllerInterface) ldr r3, [r0, #12] cbz r3, if (0U != deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy) lsrs r6, r1, #7 orr.w r6, r6, r1, lsl #1 uxtb r6, r6 mov.w r9, #12 mla r9, r9, r6, r0 ldrb.w r3, [r9, #28] cbnz r3, OSA_ENTER_CRITICAL(); add r0, sp, #4 bl deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 1U; movs r3, #1 strb.w r3, [r9, #28] OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] bl if (0U != (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)) ldr r3, [r4, #12] status = deviceHandle->controllerInterface->deviceRecv(deviceHandle->controllerHandle, endpointAddress, ldr r0, [r4, #8] if (0U != (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)) tst.w r5, #128 @ 0x80 status = deviceHandle->controllerInterface->deviceSend(deviceHandle->controllerHandle, endpointAddress, ite ne ldrne.w r9, [r3, #8] status = deviceHandle->controllerInterface->deviceRecv(deviceHandle->controllerHandle, endpointAddress, ldreq.w r9, [r3, #12] mov r1, r5 mov r3, r8 mov r2, r7 blx r9 mov r5, r0 if (kStatus_USB_Success != status) cbz r0, OSA_ENTER_CRITICAL(); add r0, sp, #4 bl deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U; movs r3, #12 mla r4, r3, r6, r4 movs r3, #0 OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U; strb r3, [r4, #28] OSA_EXIT_CRITICAL(); bl } mov r0, r5 add sp, #12 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc} return kStatus_USB_InvalidHandle; movs r5, #3 b.n status = kStatus_USB_ControllerNotFound; movs r5, #6 b.n return kStatus_USB_Busy; movs r5, #2 b.n : * @param message The device callback message handle. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) { push {r4, r5, lr} mov r4, r0 sub sp, #20 usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle; usb_device_callback_message_struct_t *message = (usb_device_callback_message_struct_t *)msg; if ((NULL == msg) || (NULL == handle)) cmp r1, #0 beq.n cmp r0, #0 beq.n { return kStatus_USB_InvalidHandle; } /* The device callback is invalid or not. */ if (NULL == deviceHandle->deviceCallback) ldr r3, [r0, #16] cmp r3, #0 beq.n uint8_t endpoint = message->code & USB_ENDPOINT_NUMBER_MASK; ldrb r2, [r1, #8] switch (deviceNotify) cmp r2, #16 uint8_t endpoint = message->code & USB_ENDPOINT_NUMBER_MASK; and.w r3, r2, #15 switch (deviceNotify) bne.n handle->isResetting = 1U; movs r3, #1 strb.w r3, [r0, #191] @ 0xbf (void)USB_DeviceControl(handle, kUSB_DeviceControlSetDefaultStatus, NULL); movs r2, #0 movs r1, #14 bl handle->deviceAddress = 0U; movs r5, #0 handle->state = (uint8_t)kUSB_DeviceStateDefault; movs r3, #2 strb.w r3, [r4, #190] @ 0xbe handle->deviceAddress = 0U; strb.w r5, [r4, #188] @ 0xbc for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++) mov r3, r4 add.w r2, r4, #168 @ 0xa8 handle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL; str r5, [r3, #20] handle->epCallback[count].callbackParam = NULL; str r5, [r3, #24] handle->epCallback[count].isBusy = 0U; strb r5, [r3, #28] for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++) adds r3, #12 cmp r3, r2 bne.n (void)handle->deviceCallback(handle, kUSB_DeviceEventBusReset, NULL); ldr r3, [r4, #16] movs r2, #0 movs r1, #1 mov r0, r4 blx r3 handle->isResetting = 0U; strb.w r5, [r4, #191] @ 0xbf status = USB_DeviceResetNotification(handle, message); movs r0, #0 return kStatus_USB_Success; #else /* Handle the notification by calling USB_DeviceNotification. */ return USB_DeviceNotification(deviceHandle, message); #endif } add sp, #20 pop {r4, r5, pc} if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS) cmp r3, #6 bhi.n if (NULL != handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn) lsls r3, r3, #1 orr.w r3, r3, r2, lsr #7 movs r2, #12 mla r2, r2, r3, r0 ldr r5, [r2, #20] cbz r5, endpointCallbackMessage.buffer = message->buffer; ldr r0, [r1, #0] str r0, [sp, #4] endpointCallbackMessage.length = message->length; ldr r0, [r1, #4] endpointCallbackMessage.isSetup = message->isSetup; ldrb r1, [r1, #9] endpointCallbackMessage.length = message->length; str r0, [sp, #8] endpointCallbackMessage.isSetup = message->isSetup; strb.w r1, [sp, #12] if (0U != message->isSetup) cbz r1, handle->epCallback[0].isBusy = 0U; movs r2, #0 strb r2, [r4, #28] handle->epCallback[1].isBusy = 0U; strb.w r2, [r4, #40] @ 0x28 status = handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn( movs r2, #12 mla r3, r2, r3, r4 add r1, sp, #4 ldr r2, [r3, #24] mov r0, r4 blx r5 b.n handle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U; strb r1, [r2, #28] b.n return kStatus_USB_InvalidHandle; movs r0, #3 b.n return kStatus_USB_Error; movs r0, #1 b.n : * @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer. Or the controller handle is invalid. * */ usb_status_t USB_DeviceRun(usb_device_handle handle) { return USB_DeviceControl(handle, kUSB_DeviceControlRun, NULL); movs r2, #0 mov r1, r2 b.w : * @retval kStatus_USB_ControllerNotFound Cannot find the controller. * @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer. Or the controller handle is invalid. */ usb_status_t USB_DeviceStop(usb_device_handle handle) { return USB_DeviceControl(handle, kUSB_DeviceControlStop, NULL); movs r2, #0 movs r1, #1 b.w : * * @retval kStatus_USB_Success The device is stopped successfully. * @retval kStatus_USB_InvalidHandle The device handle is a NULL pointer. Or the controller handle is invalid. */ usb_status_t USB_DeviceDeinit(usb_device_handle handle) { push {r0, r1, r2, r4, r5, lr} usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle; if (NULL == deviceHandle) mov r4, r0 cbz r0, { return kStatus_USB_InvalidHandle; } /* De-initialize the controller */ if (NULL != deviceHandle->controllerInterface) ldr r3, [r0, #12] cbz r3, { /* the callbackFn is initialized in USB_DeviceGetControllerInterface */ (void)deviceHandle->controllerInterface->deviceDeinit(deviceHandle->controllerHandle); ldr r3, [r3, #4] ldr r0, [r0, #8] blx r3 deviceHandle->controllerInterface = (usb_device_controller_interface_struct_t *)NULL; movs r3, #0 str r3, [r4, #12] handle->controllerHandle = NULL; movs r5, #0 OSA_ENTER_CRITICAL(); add r0, sp, #4 bl OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] handle->controllerHandle = NULL; str r5, [r4, #8] handle->controllerId = 0U; strb.w r5, [r4, #189] @ 0xbd OSA_EXIT_CRITICAL(); bl } #endif /* Free the device handle. */ (void)USB_DeviceFreeHandle(deviceHandle); return kStatus_USB_Success; mov r0, r5 } add sp, #12 pop {r4, r5, pc} return kStatus_USB_InvalidHandle; movs r0, #3 b.n ... : { stmdb sp!, {r0, r1, r4, r5, r6, r7, r8, lr} mov r6, r0 mov r7, r1 if (NULL == handle) mov r8, r2 cmp r2, #0 beq.n if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId)) ldr r4, [pc, #164] @ () OSA_ENTER_CRITICAL(); add r0, sp, #4 bl if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId)) ldr r5, [r4, #8] ldrb.w r3, [r4, #189] @ 0xbd cbnz r5, OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] s_UsbDevice[count].controllerId = controllerId; strb.w r6, [r4, #189] @ 0xbd OSA_EXIT_CRITICAL(); bl deviceHandle->deviceCallback = deviceCallback; str r7, [r4, #16] deviceHandle->controllerId = controllerId; strb.w r6, [r4, #189] @ 0xbd deviceHandle->deviceAddress = 0U; strb.w r5, [r4, #188] @ 0xbc deviceHandle->isResetting = 0U; strb.w r5, [r4, #191] @ 0xbf for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++) mov r3, r4 deviceHandle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL; mov r7, r5 for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++) adds r5, #1 cmp r5, #14 deviceHandle->epCallback[count].callbackFn = (usb_device_endpoint_callback_t)NULL; str r7, [r3, #20] deviceHandle->epCallback[count].callbackParam = NULL; str r7, [r3, #24] deviceHandle->epCallback[count].isBusy = 0U; strb r7, [r3, #28] for (count = 0U; count < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); count++) add.w r3, r3, #12 bne.n if ((kUSB_ControllerEhci0 == controlerIndex) || (kUSB_ControllerEhci1 == controlerIndex)) subs r3, r6, #2 cmp r3, #1 bls.n OSA_ENTER_CRITICAL(); add r0, sp, #4 bl OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] handle->controllerHandle = NULL; str r7, [r4, #8] handle->controllerId = 0U; strb.w r7, [r4, #189] @ 0xbd return error; movs r5, #6 OSA_EXIT_CRITICAL(); bl return kStatus_USB_Success; b.n if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId)) cmp r6, r3 OSA_EXIT_CRITICAL(); ldr r0, [sp, #4] if ((NULL != s_UsbDevice[count].controllerHandle) && (controllerId == s_UsbDevice[count].controllerId)) bne.n OSA_EXIT_CRITICAL(); bl return error; movs r5, #1 } mov r0, r5 add sp, #8 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} OSA_EXIT_CRITICAL(); bl return error; movs r5, #2 b.n *controllerInterface = (const usb_device_controller_interface_struct_t *)&s_UsbDeviceEhciInterface; ldr r3, [pc, #52] @ () str r3, [r4, #12] *handle = deviceHandle; str.w r4, [r8] error = deviceHandle->controllerInterface->deviceInit(controllerId, deviceHandle, &deviceHandle->controllerHandle); ldr r3, [r4, #12] ldr r2, [pc, #44] @ () ldr r3, [r3, #0] sub.w r1, r2, #8 mov r0, r6 blx r3 if (kStatus_USB_Success != error) mov r5, r0 cbz r0, (void)USB_DeviceDeinit(deviceHandle); ldr r0, [pc, #20] @ () bl *handle = NULL; str.w r7, [r8] return error; b.n deviceHandle->state = (uint8_t)kUSB_DeviceStateDefault; movs r3, #2 strb.w r3, [r4, #190] @ 0xbe return error; b.n return kStatus_USB_InvalidHandle; movs r5, #3 b.n .word 0x200012e0 .word 0x60009008 .word 0x200012e8 : */ usb_status_t USB_DeviceSendRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length) { return USB_DeviceTransfer( handle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), and.w r1, r1, #15 return USB_DeviceTransfer( orr.w r1, r1, #128 @ 0x80 b.w : * The subsequent transfer could begin only when the previous transfer is done (get notification through the endpoint * callback). */ usb_status_t USB_DeviceRecvRequest(usb_device_handle handle, uint8_t endpointAddress, uint8_t *buffer, uint32_t length) { return USB_DeviceTransfer( and.w r1, r1, #15 b.w : * @retval kStatus_USB_ControllerNotFound Cannot find the controller. */ usb_status_t USB_DeviceInitEndpoint(usb_device_handle handle, usb_device_endpoint_init_struct_t *epInit, usb_device_endpoint_callback_struct_t *epCallback) { push {r4, r5, r6} usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle; uint8_t endpoint; uint8_t direction; if (NULL == deviceHandle) cbz r0, { return kStatus_USB_InvalidHandle; } if ((NULL == epInit) || (NULL == epCallback)) cbz r1, cbz r2, { return kStatus_USB_InvalidParameter; } endpoint = epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK; ldrb r4, [r1, #2] and.w r5, r4, #15 direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT; if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS) cmp r5, #6 bhi.n direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> lsrs r4, r4, #7 { deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn = epCallback->callbackFn; orr.w r4, r4, r5, lsl #1 movs r6, #12 mla r3, r6, r4, r0 ldr r5, [r2, #0] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam = epCallback->callbackParam; ldr r2, [r2, #4] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam = str r2, [r3, #24] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U; movs r2, #0 strb r2, [r3, #28] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn = epCallback->callbackFn; str r5, [r3, #20] } else { return kStatus_USB_InvalidParameter; } return USB_DeviceControl(handle, kUSB_DeviceControlEndpointInit, epInit); mov r2, r1 } pop {r4, r5, r6} return USB_DeviceControl(handle, kUSB_DeviceControlEndpointInit, epInit); movs r1, #2 b.w return kStatus_USB_InvalidHandle; movs r0, #3 } pop {r4, r5, r6} bx lr return kStatus_USB_InvalidParameter; movs r0, #4 b.n : * @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS. * @retval kStatus_USB_Busy The endpoint is busy in EHCI driver. * @retval kStatus_USB_ControllerNotFound Cannot find the controller. */ usb_status_t USB_DeviceDeinitEndpoint(usb_device_handle handle, uint8_t endpointAddress) { push {r0, r1, r4, r5, r6, lr} mov r4, r1 strb.w r1, [sp, #7] usb_device_struct_t *deviceHandle = (usb_device_struct_t *)handle; uint8_t endpoint = endpointAddress & USB_ENDPOINT_NUMBER_MASK; and.w r6, r1, #15 usb_status_t status; #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U)) OSA_SR_ALLOC(); #endif if (NULL == deviceHandle) mov r5, r0 cbz r0, #if (defined(USB_DEVICE_CONFIG_USE_TASK) && (USB_DEVICE_CONFIG_USE_TASK > 0U)) OSA_ENTER_CRITICAL(); deviceHandle->epCallbackDirectly = 1U; OSA_EXIT_CRITICAL(); #endif status = USB_DeviceControl(handle, kUSB_DeviceControlEndpointDeinit, &endpointAddress); add.w r2, sp, #7 movs r1, #3 bl OSA_ENTER_CRITICAL(); deviceHandle->epCallbackDirectly = 0U; OSA_EXIT_CRITICAL(); #endif if (endpoint < USB_DEVICE_CONFIG_ENDPOINTS) cmp r6, #6 bhi.n uint8_t direction = (endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> lsrs r4, r4, #7 { deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackFn = orr.w r4, r4, r6, lsl #1 movs r3, #12 mla r3, r3, r4, r5 movs r2, #0 str r2, [r3, #20] (usb_device_endpoint_callback_t)NULL; deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].callbackParam = NULL; str r2, [r3, #24] deviceHandle->epCallback[(uint8_t)((uint32_t)endpoint << 1U) | direction].isBusy = 0U; strb r2, [r3, #28] else { return kStatus_USB_InvalidParameter; } return status; } add sp, #8 pop {r4, r5, r6, pc} return kStatus_USB_InvalidHandle; movs r0, #3 b.n return kStatus_USB_InvalidParameter; movs r0, #4 b.n : * @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid. * @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS. * @retval kStatus_USB_ControllerNotFound Cannot find the controller. */ usb_status_t USB_DeviceStallEndpoint(usb_device_handle handle, uint8_t endpointAddress) { push {r0, r1, r2, lr} strb.w r1, [sp, #7] if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS) and.w r1, r1, #15 cmp r1, #6 bhi.n { return USB_DeviceControl(handle, kUSB_DeviceControlEndpointStall, &endpointAddress); add.w r2, sp, #7 movs r1, #4 bl } else { return kStatus_USB_InvalidParameter; } } add sp, #12 ldr.w pc, [sp], #4 return kStatus_USB_InvalidParameter; movs r0, #4 b.n : * @retval kStatus_USB_InvalidHandle The handle is a NULL pointer. Or the controller handle is invalid. * @retval kStatus_USB_InvalidParameter The endpoint number is more than USB_DEVICE_CONFIG_ENDPOINTS. * @retval kStatus_USB_ControllerNotFound Cannot find the controller. */ usb_status_t USB_DeviceUnstallEndpoint(usb_device_handle handle, uint8_t endpointAddress) { push {r0, r1, r2, lr} strb.w r1, [sp, #7] if ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) < USB_DEVICE_CONFIG_ENDPOINTS) and.w r1, r1, #15 cmp r1, #6 bhi.n { return USB_DeviceControl(handle, kUSB_DeviceControlEndpointUnstall, &endpointAddress); add.w r2, sp, #7 movs r1, #5 bl } else { return kStatus_USB_InvalidParameter; } } add sp, #12 ldr.w pc, [sp], #4 return kStatus_USB_InvalidParameter; movs r0, #4 b.n : usb_status_t USB_DeviceGetStatus(usb_device_handle handle, usb_device_status_t type, void *param) { uint8_t *temp8; usb_status_t status = kStatus_USB_Error; if (NULL == param) cbz r2, { return kStatus_USB_InvalidParameter; } switch (type) subs r1, #2 cmp r1, #6 bhi.n tbb [pc, r1] .word 0x13110704 .short 0x0e09 .byte 0x15 .byte 0x00 case kUSB_DeviceStatusGetCurrentFrameCount: status = USB_DeviceControl(handle, kUSB_DeviceControlGetCurrentFrameCount, param); break; #endif case kUSB_DeviceStatusSpeed: status = USB_DeviceControl(handle, kUSB_DeviceControlGetSpeed, param); movs r1, #15 break; case kUSB_DeviceStatusEndpoint: status = USB_DeviceControl(handle, kUSB_DeviceControlGetEndpointStatus, param); break; case kUSB_DeviceStatusSynchFrame: status = USB_DeviceControl(handle, kUSB_DeviceControlGetSynchFrame, param); b.w status = USB_DeviceControl(handle, kUSB_DeviceControlGetOtgStatus, param); movs r1, #16 b.n *temp8 = ((usb_device_struct_t *)handle)->state; ldrb.w r3, [r0, #190] @ 0xbe strb r3, [r2, #0] status = kStatus_USB_Success; movs r0, #0 bx lr *temp8 = ((usb_device_struct_t *)handle)->deviceAddress; ldrb.w r3, [r0, #188] @ 0xbc b.n status = USB_DeviceControl(handle, kUSB_DeviceControlGetDeviceStatus, param); movs r1, #6 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlGetEndpointStatus, param); movs r1, #7 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlGetSynchFrame, param); movs r1, #9 b.n return kStatus_USB_InvalidParameter; movs r0, #4 bx lr switch (type) movs r0, #1 default: /*no action*/ break; } return status; } bx lr : * @retval kStatus_USB_Error Unsupported type, or the param is NULL pointer. */ usb_status_t USB_DeviceSetStatus(usb_device_handle handle, usb_device_status_t type, void *param) { usb_status_t status = kStatus_USB_Error; switch (type) subs r1, #3 cmp r1, #11 bhi.n tbb [pc, r1] .word 0x092a2a06 .word 0x262a2a0f .word 0x242a2228 case kUSB_DeviceStatusTestMode: status = USB_DeviceControl(handle, kUSB_DeviceControlSetTestMode, param); break; #endif case kUSB_DeviceStatusOtg: status = USB_DeviceControl(handle, kUSB_DeviceControlSetOtgStatus, param); movs r1, #17 #endif case kUSB_DeviceStatusBusSuspend: status = USB_DeviceControl(handle, kUSB_DeviceControlSuspend, param); break; case kUSB_DeviceStatusBusSleep: status = USB_DeviceControl(handle, kUSB_DeviceControlSleep, param); b.w if (NULL != param) cbz r2, ((usb_device_struct_t *)handle)->state = (uint8_t)(*(uint8_t *)param); ldrb r3, [r2, #0] strb.w r3, [r0, #190] @ 0xbe status = kStatus_USB_Success; movs r0, #0 bx lr if ((uint8_t)kUSB_DeviceStateAddressing != ((usb_device_struct_t *)handle)->state) ldrb.w r3, [r0, #190] @ 0xbe cmp r3, #3 beq.n if (NULL != param) cbz r2, ((usb_device_struct_t *)handle)->deviceAddress = (uint8_t)(*(uint8_t *)param); ldrb r3, [r2, #0] strb.w r3, [r0, #188] @ 0xbc ((usb_device_struct_t *)handle)->state = (uint8_t)kUSB_DeviceStateAddressing; movs r3, #3 strb.w r3, [r0, #190] @ 0xbe status = USB_DeviceControl(handle, kUSB_DeviceControlPreSetDeviceAddress, add.w r2, r0, #188 @ 0xbc movs r1, #20 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlSetDeviceAddress, add.w r2, r0, #188 @ 0xbc movs r1, #8 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlResume, param); movs r1, #10 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlSleepResume, param); movs r1, #11 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlSuspend, param); movs r1, #12 b.n status = USB_DeviceControl(handle, kUSB_DeviceControlSleep, param); movs r1, #13 b.n usb_status_t status = kStatus_USB_Error; movs r0, #1 default: /*no action*/ break; } return status; } bx lr : * * @param ehciState Pointer of the device EHCI state structure. * */ static void USB_DeviceEhciSetDefaultState(usb_device_ehci_state_struct_t *ehciState) { push {r4, r5, r6, r7, lr} usb_device_ehci_dtd_struct_t *p; /* Initialize the dtd free queue */ ehciState->dtdFree = ehciState->dtd; ldr r3, [r0, #12] str r3, [r0, #16] p = ehciState->dtdFree; for (uint32_t i = 1U; i < USB_DEVICE_CONFIG_EHCI_MAX_DTD; i++) add.w r2, r3, #32 add.w r1, r3, #512 @ 0x200 { p->nextDtdPointer = (uint32_t)&ehciState->dtd[i]; str r2, [r3, #0] for (uint32_t i = 1U; i < USB_DEVICE_CONFIG_EHCI_MAX_DTD; i++) adds r2, #32 cmp r2, r1 p = (usb_device_ehci_dtd_struct_t *)p->nextDtdPointer; ldr r3, [r3, #0] for (uint32_t i = 1U; i < USB_DEVICE_CONFIG_EHCI_MAX_DTD; i++) bne.n } p->nextDtdPointer = 0U; movs r1, #0 str r1, [r3, #0] ehciState->dtdCount = USB_DEVICE_CONFIG_EHCI_MAX_DTD; movs r3, #16 strb.w r3, [r0, #132] @ 0x84 /* Not use interrupt threshold. */ ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_ITC_MASK; ldr r3, [r0, #4] ldr r5, [r0, #8] ldr.w r2, [r3, #320] @ 0x140 bic.w r2, r2, #16711680 @ 0xff0000 str.w r2, [r3, #320] @ 0x140 ehciState->registerBase->USBCMD |= USBHS_USBCMD_ITC(0U); ldr.w r2, [r3, #320] @ 0x140 str.w r2, [r3, #320] @ 0x140 /* Disable setup lockout, please refer to "Control Endpoint Operation" section in RM. */ ehciState->registerBase->USBMODE |= USBHS_USBMODE_SLOM_MASK; ldr.w r2, [r3, #424] @ 0x1a8 orr.w r2, r2, #8 str.w r2, [r3, #424] @ 0x1a8 /* Set the endian by using CPU's endian */ #if (ENDIANNESS == USB_BIG_ENDIAN) ehciState->registerBase->USBMODE |= USBHS_USBMODE_ES_MASK; #else ehciState->registerBase->USBMODE &= ~USBHS_USBMODE_ES_MASK; ldr.w r2, [r3, #424] @ 0x1a8 bic.w r2, r2, #4 str.w r2, [r3, #424] @ 0x1a8 #endif /* Initialize the QHs of endpoint. */ for (uint32_t i = 0U; i < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); i++) add.w r4, r0, #16 add.w r7, r0, #72 @ 0x48 { ehciState->qh[i].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; mov r2, r5 mov.w lr, #1 ehciState->qh[i].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize = mov.w ip, #64 @ 0x40 ehciState->qh[i].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; str.w lr, [r2, #8] ehciState->qh[i].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize = ldr r6, [r2, #0] bfi r6, ip, #16, #11 str r6, [r2, #0] USB_CONTROL_MAX_PACKET_SIZE; ehciState->dtdHard[i] = NULL; str.w r1, [r4, #4]! ehciState->dtdTail[i] = NULL; ehciState->qh[i].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; ldrb.w r6, [r2, #56] @ 0x38 ehciState->dtdTail[i] = NULL; str r1, [r4, #56] @ 0x38 ehciState->qh[i].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; bfi r6, r1, #0, #1 for (uint32_t i = 0U; i < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); i++) cmp r4, r7 ehciState->qh[i].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; strb.w r6, [r2, #56] @ 0x38 for (uint32_t i = 0U; i < (USB_DEVICE_CONFIG_ENDPOINTS * 2U); i++) add.w r2, r2, #64 @ 0x40 bne.n ehciState->registerBase->OTGSC = ehciState->registerBase->OTGSC & 0x0000FFFFU; ehciState->registerBase->OTGSC |= USBHS_OTGSC_BSVIE_MASK; #endif /* USB_DEVICE_CONFIG_DETACH_ENABLE */ /* Enable USB Interrupt, USB Error Interrupt, Port Change detect Interrupt, USB-Reset Interrupt*/ ehciState->registerBase->USBINTR = movs r2, #199 @ 0xc7 ehciState->registerBase->EPLISTADDR = (uint32_t)ehciState->qh; str.w r5, [r3, #344] @ 0x158 ehciState->registerBase->DEVICEADDR = 0U; str.w r1, [r3, #340] @ 0x154 ehciState->registerBase->USBINTR = str.w r2, [r3, #328] @ 0x148 | USBHS_USBINTR_SLE_MASK #endif /* USB_DEVICE_CONFIG_LOW_POWER_MODE */ ); /* Clear reset flag */ ehciState->isResetting = 0U; strb.w r1, [r0, #134] @ 0x86 } pop {r4, r5, r6, r7, pc} ... : */ static usb_status_t USB_DeviceEhciTransfer(usb_device_ehci_state_struct_t *ehciState, uint8_t endpointAddress, uint8_t *buffer, uint32_t length) { stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} mov r5, r1 sub sp, #28 mov r6, r3 usb_device_ehci_dtd_struct_t *dtd; usb_device_ehci_dtd_struct_t *dtdHard; uint32_t index = (((uint32_t)endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) | (((uint32_t)endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> lsrs r3, r1, #7 uint32_t index = (((uint32_t)endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) | lsls r1, r1, #1 and.w r1, r1, #30 { str r2, [sp, #12] (((uint32_t)endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> str r3, [sp, #0] uint32_t index = (((uint32_t)endpointAddress & USB_ENDPOINT_NUMBER_MASK) << 1U) | orr.w r9, r1, r5, lsr #7 uint8_t waitingSafelyAccess = 1U; uint32_t primeTimesCount = 0U; void *temp; OSA_SR_ALLOC(); if (NULL == ehciState) mov r4, r0 cmp r0, #0 beq.w { return kStatus_USB_InvalidHandle; } if (0U == ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened) ldr r3, [r0, #8] add.w r3, r3, r9, lsl #6 mov.w r8, r9, lsl #6 ldrb.w r3, [r3, #56] @ 0x38 ands.w r3, r3, #1 str r3, [sp, #4] beq.n { return kStatus_USB_Error; } /* Return error when ehci is doing reset */ if (0U != ehciState->isResetting) ldrb.w r7, [r0, #134] @ 0x86 cbz r7, return kStatus_USB_Error; movs r7, #1 } } OSA_EXIT_CRITICAL(); return kStatus_USB_Success; } mov r0, r7 add sp, #28 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} uint32_t dtdRequestCount = (length + USB_DEVICE_ECHI_DTD_TOTAL_BYTES - 1U) / USB_DEVICE_ECHI_DTD_TOTAL_BYTES; add.w r3, r6, #16320 @ 0x3fc0 adds r3, #63 @ 0x3f if (0U == dtdRequestCount) cmp.w r3, #16384 @ 0x4000 OSA_ENTER_CRITICAL(); add r0, sp, #20 uint32_t dtdRequestCount = (length + USB_DEVICE_ECHI_DTD_TOTAL_BYTES - 1U) / USB_DEVICE_ECHI_DTD_TOTAL_BYTES; ite cs movcs.w sl, r3, lsr #14 dtdRequestCount = 1U; movcc.w sl, #1 OSA_ENTER_CRITICAL(); bl if (dtdRequestCount > (uint32_t)ehciState->dtdCount) ldrb.w r3, [r4, #132] @ 0x84 cmp r3, sl bcs.n OSA_EXIT_CRITICAL(); ldr r0, [sp, #20] bl return kStatus_USB_Busy; movs r7, #2 b.n add.w r1, r4, r9, lsl #2 uint8_t qhIdle = 0U; mov.w ip, #0 ldr r2, [r1, #76] @ 0x4c uint32_t currentIndex = 0U; mov lr, ip if (length > USB_DEVICE_ECHI_DTD_TOTAL_BYTES) mov sl, r2 dtd = ehciState->dtdFree; ldr r2, [r4, #16] str r6, [sp, #8] ehciState->dtdFree = (usb_device_ehci_dtd_struct_t *)dtd->nextDtdPointer; ldr r0, [r2, #0] str r0, [r4, #16] ehciState->dtdCount--; ldrb.w r0, [r4, #132] @ 0x84 subs r0, #1 strb.w r0, [r4, #132] @ 0x84 dtd->nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; movs r0, #1 str r0, [r2, #0] dtd->dtdTokenUnion.dtdToken = 0U; movs r0, #0 str r0, [r2, #4] dtd->bufferPointerPage[0] = (uint32_t)(buffer + currentIndex); ldr r0, [sp, #12] add r0, lr str r0, [r2, #8] (dtd->bufferPointerPage[0] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK) & USB_DEVICE_ECHI_DTD_PAGE_MASK; ldr r0, [r2, #8] add.w r0, r0, #4096 @ 0x1000 bfc r0, #0, #12 dtd->bufferPointerPage[1] = str r0, [r2, #12] dtd->bufferPointerPage[2] = dtd->bufferPointerPage[1] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK; ldr r0, [r2, #12] add.w r0, r0, #4096 @ 0x1000 str r0, [r2, #16] dtd->bufferPointerPage[3] = dtd->bufferPointerPage[2] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK; ldr r0, [r2, #16] add.w r0, r0, #4096 @ 0x1000 str r0, [r2, #20] dtd->bufferPointerPage[4] = dtd->bufferPointerPage[3] + USB_DEVICE_ECHI_DTD_PAGE_BLOCK; ldr r0, [r2, #20] add.w r0, r0, #4096 @ 0x1000 str r0, [r2, #24] dtd->dtdTokenUnion.dtdTokenBitmap.totalBytes = sendLength; ldr r0, [r2, #4] if (length > USB_DEVICE_ECHI_DTD_TOTAL_BYTES) cmp.w r6, #16384 @ 0x4000 mov r3, r6 it cs movcs.w r3, #16384 @ 0x4000 dtd->dtdTokenUnion.dtdTokenBitmap.totalBytes = sendLength; bfi r0, r3, #16, #15 str r0, [r2, #4] dtd->reservedUnion.originalBufferInfo.originalBufferLength = sendLength; ldr r0, [r2, #28] dtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_OFFSET_MASK; ldr.w r9, [r2, #8] dtd->reservedUnion.originalBufferInfo.originalBufferLength = sendLength; bfi r0, r3, #12, #19 str r0, [r2, #28] dtd->reservedUnion.originalBufferInfo.originalBufferOffest = bic.w r0, r0, #2147483648 @ 0x80000000 bic.w r0, r0, #4080 @ 0xff0 ubfx r9, r9, #0, #12 bic.w r0, r0, #15 orr.w r0, r0, r9 dtdHard = dtd; cmp.w lr, #0 it eq moveq fp, r2 if (0U == length) subs r6, r6, r3 dtd->reservedUnion.originalBufferInfo.originalBufferOffest = str r0, [r2, #28] dtd->dtdTokenUnion.dtdTokenBitmap.ioc = 1U; ittt eq ldreq r0, [r2, #4] orreq.w r0, r0, #32768 @ 0x8000 streq r0, [r2, #4] dtd->dtdTokenUnion.dtdTokenBitmap.status = USB_DEVICE_ECHI_DTD_STATUS_ACTIVE; ldr r0, [r2, #4] mov.w r9, #128 @ 0x80 bfi r0, r9, #0, #8 str r0, [r2, #4] currentIndex += sendLength; add lr, r3 if (NULL != (ehciState->dtdTail[index])) cmp.w sl, #0 beq.n ehciState->dtdTail[index]->nextDtdPointer = (uint32_t)dtd; str.w r2, [sl] } while (0U != length); cmp r6, #0 bne.n if ((USB_CONTROL_ENDPOINT == (endpointAddress & USB_ENDPOINT_NUMBER_MASK)) && str r2, [r1, #76] @ 0x4c ands.w r2, r5, #15 bne.n ldr r1, [sp, #0] cbz r1, temp = (void *)&ehciState->qh[setupindex].setupBufferBack[0]; ldr r0, [r4, #8] if (1U == ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.zlt) add.w r1, r0, r8 ldrb.w r1, [r1, #56] @ 0x38 lsls r1, r1, #30 bpl.n if ((0U != sendLength) && (sendLength < deviceSetup->wLength) && ldr r1, [sp, #8] cbz r1, ldrh r1, [r0, #54] @ 0x36 cmp r3, r1 bcs.n .capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize))) ldr.w r1, [r0, r8] ubfx r1, r1, #16, #11 (sendLength % ehciState->qh[index] udiv lr, r3, r1 mls r3, r1, lr, r3 if ((0U != sendLength) && (sendLength < deviceSetup->wLength) && cbnz r3, ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = 0U; ldr.w r3, [r0, r8] bfi r3, r6, #29, #1 str.w r3, [r0, r8] ((endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U)); lsrs r5, r5, #3 and.w r5, r5, #16 uint32_t primeBit = 1UL << ((endpointAddress & USB_ENDPOINT_NUMBER_MASK) + orrs r5, r2 movs r3, #1 lsls r3, r5 if (0U == qhIdle) cmp.w ip, #0 bne.n if (0U != (ehciState->registerBase->EPPRIME & primeBit)) ldr r2, [r4, #4] ldr.w r1, [r2, #432] @ 0x1b0 tst r1, r3 beq.n OSA_EXIT_CRITICAL(); ldr r0, [sp, #20] bl return kStatus_USB_Success; b.n qhIdle = 1U; ldr.w ip, [sp, #4] ehciState->dtdHard[index] = dtd; str r2, [r1, #20] qhIdle = 1U; b.n ehciState->registerBase->USBCMD |= USBHS_USBCMD_ATDTW_MASK; ldr.w r1, [r2, #320] @ 0x140 orr.w r1, r1, #4096 @ 0x1000 str.w r1, [r2, #320] @ 0x140 epStatus = ehciState->registerBase->EPSR; ldr.w r0, [r2, #440] @ 0x1b8 if (0U != (ehciState->registerBase->USBCMD & USBHS_USBCMD_ATDTW_MASK)) ldr.w r1, [r2, #320] @ 0x140 lsls r1, r1, #19 bpl.n ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_ATDTW_MASK; ldr.w r1, [r2, #320] @ 0x140 if ((0U != qhIdle) || (0U == (epStatus & primeBit))) tst r3, r0 ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_ATDTW_MASK; bic.w r1, r1, #4096 @ 0x1000 str.w r1, [r2, #320] @ 0x140 if ((0U != qhIdle) || (0U == (epStatus & primeBit))) bne.n ehciState->qh[index].nextDtdPointer = (uint32_t)dtdHard; ldr r2, [r4, #8] add r2, r8 ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; movs r1, #0 ehciState->qh[index].nextDtdPointer = (uint32_t)dtdHard; str.w fp, [r2, #8] ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; str r1, [r2, #12] __ASM volatile ("dsb 0xF":::"memory"); dsb sy ehciState->registerBase->EPPRIME = primeBit; ldr r2, [r4, #4] while (0U == (ehciState->registerBase->EPSR & primeBit)) ldr r1, [pc, #40] @ () ehciState->registerBase->EPPRIME = primeBit; str.w r3, [r2, #432] @ 0x1b0 while (0U == (ehciState->registerBase->EPSR & primeBit)) ldr.w r0, [r2, #440] @ 0x1b8 tst r0, r3 bne.n if (primeTimesCount == USB_DEVICE_MAX_TRANSFER_PRIME_TIMES) subs r1, #1 bne.n OSA_EXIT_CRITICAL(); ldr r0, [sp, #20] bl return kStatus_USB_Error; b.n if (0U != (ehciState->registerBase->EPCOMPLETE & primeBit)) ldr.w r0, [r2, #444] @ 0x1bc tst r0, r3 bne.n ehciState->registerBase->EPPRIME = primeBit; str.w r3, [r2, #432] @ 0x1b0 b.n return kStatus_USB_InvalidHandle; movs r7, #3 b.n .word 0x00989680 : { stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} uint32_t index = ((uint32_t)endpoint << 1U) + (uint32_t)direction; add.w r9, r2, r1, lsl #1 message.buffer = NULL; add.w r8, r0, r9, lsl #2 movs r6, #0 (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); ldr.w r4, [r8, #20] message.buffer = (uint8_t *)((bufferAddress & USB_DEVICE_ECHI_DTD_PAGE_MASK) | ldr.w sl, [pc, #184] @ message.buffer = NULL; str r6, [sp, #4] message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); orr.w r1, r1, r2, lsl #7 { mov r5, r0 message.length = 0U; str r6, [sp, #8] (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); bic.w r4, r4, #31 ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; mov.w r9, r9, lsl #6 message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); uxtb r7, r1 while (NULL != currentDtd) cbnz r4, } add sp, #16 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} if (NULL == message.buffer) ldr r3, [sp, #4] cbnz r3, uint32_t bufferAddress = currentDtd->bufferPointerPage[0]; ldr r3, [r4, #8] (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ldrh r2, [r4, #28] message.buffer = (uint8_t *)((bufferAddress & USB_DEVICE_ECHI_DTD_PAGE_MASK) | and.w r3, r3, sl (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ubfx r2, r2, #0, #12 message.buffer = (uint8_t *)((bufferAddress & USB_DEVICE_ECHI_DTD_PAGE_MASK) | orrs r3, r2 str r3, [sp, #4] if (0U != (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) ldr r3, [r4, #4] lsls r2, r3, #24 currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes); itttt pl ldrpl r2, [r4, #4] message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength - ldrpl r3, [r4, #28] currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes); ubfxpl r2, r2, #16, #15 message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength - ubfxpl r3, r3, #12, #19 ittet pl subpl r3, r3, r2 ldrpl r2, [sp, #8] message.length = USB_CANCELLED_TRANSFER_LENGTH; movmi.w r3, #4294967295 @ 0xffffffff message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength - addpl r3, r3, r2 str r3, [sp, #8] if (ehciState->dtdHard[index] == ehciState->dtdTail[index]) ldr.w r2, [r8, #76] @ 0x4c ldr.w r3, [r8, #20] cmp r3, r2 bne.n ehciState->dtdHard[index] = NULL; str.w r6, [r8, #20] ehciState->dtdTail[index] = NULL; str.w r6, [r8, #76] @ 0x4c ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; ldr r3, [r5, #8] add r3, r9 movs r2, #1 str r2, [r3, #8] ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; str r6, [r3, #12] if ((0U != currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) || ldr r3, [r4, #4] lsls r3, r3, #16 bmi.n ldr.w r3, [r8, #20] cmp r3, #31 bhi.n (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r5, #0] message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); strb.w r7, [sp, #12] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); add r1, sp, #4 message.isSetup = 0U; strb.w r6, [sp, #13] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); bl message.buffer = NULL; str r6, [sp, #4] message.length = 0U; str r6, [sp, #8] currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; ldr r3, [r5, #16] currentDtd->dtdTokenUnion.dtdToken = 0U; str r6, [r4, #4] currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; str r3, [r4, #0] ehciState->dtdCount++; ldrb.w r3, [r5, #132] @ 0x84 ehciState->dtdFree = currentDtd; str r4, [r5, #16] ehciState->dtdCount++; adds r3, #1 strb.w r3, [r5, #132] @ 0x84 (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); ldr.w r4, [r8, #20] bic.w r4, r4, #31 b.n ehciState->dtdHard[index] = (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer; ldr r3, [r3, #0] str.w r3, [r8, #20] b.n nop .word 0xfffff000 : * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceEhciInit(uint8_t controllerId, usb_device_handle handle, usb_device_controller_handle *ehciHandle) { push {r0, r1, r4, r5, r6, lr} usb_device_ehci_state_struct_t *ehciState = NULL; uint32_t ehci_base[] = USBHS_BASE_ADDRS; ldr r3, [pc, #144] @ () str r3, [sp, #0] add.w r3, r3, #512 @ 0x200 str r3, [sp, #4] uint8_t index; usb_phydcd_config_struct_t phyDcdParamConfig; usb_phydcd_status_t phyDcdError = kStatus_phydcd_Success; #endif if ((controllerId < (uint8_t)kUSB_ControllerEhci0) || subs r3, r0, #2 { mov r6, r2 if ((controllerId < (uint8_t)kUSB_ControllerEhci0) || uxtb r2, r3 cmp r2, #1 bls.n ((uint32_t)((uint32_t)controllerId - (uint32_t)kUSB_ControllerEhci0) >= (sizeof(ehci_base) / sizeof(uint32_t)))) { return kStatus_USB_ControllerNotFound; movs r5, #6 b.n g_UsbDeviceEhciStateStatus[instance] = 1U; movs r4, #1 strb r4, [r2, #0] ehciState = USB_EhciGetValidEhciState(&intanceIndex); if (NULL == ehciState) { return kStatus_USB_InvalidHandle; } ehciState->dtd = s_UsbDeviceEhciDtd[intanceIndex]; ldr r4, [pc, #120] @ () ldr r2, [pc, #120] @ () str r2, [r4, #12] temp = (void *)&qh_buffer[intanceIndex * 2048U]; ehciState->qh = (usb_device_ehci_qh_struct_t *)temp; ldr r2, [pc, #120] @ () str r2, [r4, #8] ehciState->controllerId = controllerId; ehciState->registerBase = (USBHS_Type *)ehci_base[controllerId - (uint8_t)kUSB_ControllerEhci0]; add r2, sp, #8 add.w r3, r2, r3, lsl #2 ehciState->controllerId = controllerId; strb.w r0, [r4, #135] @ 0x87 ehciState->registerBase = (USBHS_Type *)ehci_base[controllerId - (uint8_t)kUSB_ControllerEhci0]; ldr.w r3, [r3, #-8] str r3, [r4, #4] ehciState->registerNcBase = (USBNC_Type *)USB_EhciNCGetBase(controllerId); #endif #endif /* Reset the controller. */ ehciState->registerBase->USBCMD |= USBHS_USBCMD_RST_MASK; ldr.w r2, [r3, #320] @ 0x140 orr.w r2, r2, #2 str.w r2, [r3, #320] @ 0x140 while (0U != (ehciState->registerBase->USBCMD & USBHS_USBCMD_RST_MASK)) ldr.w r2, [r3, #320] @ 0x140 lsls r2, r2, #30 bmi.n { } /* Get the HW's endpoint count */ ehciState->endpointCount = (uint8_t)((ehciState->registerBase->DCCPARAMS & USBHS_DCCPARAMS_DEN_MASK) >> USBHS_DCCPARAMS_DEN_SHIFT); ldr.w r0, [r3, #292] @ 0x124 and.w r0, r0, #31 if (ehciState->endpointCount < USB_DEVICE_CONFIG_ENDPOINTS) cmp r0, #6 ehciState->endpointCount = strb.w r0, [r4, #133] @ 0x85 if (ehciState->endpointCount < USB_DEVICE_CONFIG_ENDPOINTS) bls.n return kStatus_USB_Error; } ehciState->deviceHandle = (usb_device_struct_t *)handle; /* Clear the controller mode field and set to device mode. */ ehciState->registerBase->USBMODE &= ~USBHS_USBMODE_CM_MASK; ldr.w r2, [r3, #424] @ 0x1a8 ehciState->registerBase->USBMODE |= USBHS_USBMODE_CM(0x02U); /* Set the EHCI to default status. */ USB_DeviceEhciSetDefaultState(ehciState); ldr r0, [pc, #52] @ () ehciState->deviceHandle = (usb_device_struct_t *)handle; str r1, [r4, #0] ehciState->registerBase->USBMODE &= ~USBHS_USBMODE_CM_MASK; bic.w r2, r2, #3 str.w r2, [r3, #424] @ 0x1a8 ehciState->registerBase->USBMODE |= USBHS_USBMODE_CM(0x02U); ldr.w r2, [r3, #424] @ 0x1a8 orr.w r2, r2, #2 str.w r2, [r3, #424] @ 0x1a8 USB_DeviceEhciSetDefaultState(ehciState); bl *ehciHandle = (usb_device_controller_handle)ehciState; str r4, [r6, #0] (void)USB_PHYDCD_Control(ehciState->dcdHandle, kUSB_DevicePHYDcdRun, NULL); } #endif return kStatus_USB_Success; b.n if (0U == g_UsbDeviceEhciStateStatus[instance]) ldr r2, [pc, #32] @ () ldrb r5, [r2, #0] cmp r5, #0 beq.n return kStatus_USB_InvalidHandle; movs r5, #3 } mov r0, r5 add sp, #8 pop {r4, r5, r6, pc} return kStatus_USB_Error; movs r5, #1 b.n .word 0x402e0000 .word 0x200013a4 .word 0x20001440 .word 0x20001800 .word 0x200013a0 : */ usb_status_t USB_DeviceEhciDeinit(usb_device_controller_handle ehciHandle) { usb_device_ehci_state_struct_t *ehciState = (usb_device_ehci_state_struct_t *)ehciHandle; if (NULL == ehciHandle) cbnz r0, { return kStatus_USB_InvalidHandle; movs r0, #3 (defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)) (void)USB_PHYDCD_Deinit(ehciState->dcdHandle); #endif return kStatus_USB_Success; } bx lr if (ehciState == &g_UsbDeviceEhciState[instance]) ldr r3, [pc, #44] @ () cmp r0, r3 bne.n ldr r3, [pc, #40] @ () movs r2, #0 strb r2, [r3, #0] ehciState->registerBase->USBINTR = 0U; ldr r3, [r0, #4] movs r0, #0 str.w r0, [r3, #328] @ 0x148 ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_RS_MASK; ldr.w r2, [r3, #320] @ 0x140 bic.w r2, r2, #1 str.w r2, [r3, #320] @ 0x140 ehciState->registerBase->USBCMD |= USBHS_USBCMD_RST_MASK; ldr.w r2, [r3, #320] @ 0x140 orr.w r2, r2, #2 str.w r2, [r3, #320] @ 0x140 return kStatus_USB_Success; bx lr .word 0x200013a4 .word 0x200013a0 : uint32_t length) { /* Add dtd to the QH */ return USB_DeviceEhciTransfer( (usb_device_ehci_state_struct_t *)ehciHandle, (endpointAddress & USB_ENDPOINT_NUMBER_MASK) | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT), and.w r1, r1, #15 return USB_DeviceEhciTransfer( orr.w r1, r1, #128 @ 0x80 b.w : uint8_t endpointAddress, uint8_t *buffer, uint32_t length) { /* Add dtd to the QH */ return USB_DeviceEhciTransfer( and.w r1, r1, #15 b.w : * @param ep Endpoint address, bit7 is the direction of endpoint, 1U - IN, 0U - OUT. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceEhciCancel(usb_device_controller_handle ehciHandle, uint8_t ep) { stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, lr} usb_device_ehci_state_struct_t *ehciState = (usb_device_ehci_state_struct_t *)ehciHandle; usb_device_callback_message_struct_t message; usb_device_ehci_dtd_struct_t *currentDtd; uint32_t primeBit = 1UL << ((ep & USB_ENDPOINT_NUMBER_MASK) + ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U)); lsrs r3, r1, #3 and.w r2, r1, #15 and.w r3, r3, #16 orrs r3, r2 uint8_t index = ((ep & USB_ENDPOINT_NUMBER_MASK) << 1U) | ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x07U); lsls r2, r1, #1 uint32_t primeBit = movs r6, #1 ((ep & USB_ENDPOINT_NUMBER_MASK) << 1U) | ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x07U); and.w r2, r2, #30 { mov r5, r1 uint32_t primeBit = lsls r6, r3 uint8_t index = orr.w r4, r2, r1, lsr #7 uint8_t flag = 0; OSA_SR_ALLOC(); if (NULL == ehciHandle) mov r7, r0 cmp r0, #0 beq.n { return kStatus_USB_InvalidHandle; } OSA_ENTER_CRITICAL(); mov r0, sp bl message.buffer = NULL; movs r3, #0 add.w r2, r7, r4, lsl #2 str r3, [sp, #4] message.length = USB_CANCELLED_TRANSFER_LENGTH; mov.w r3, #4294967295 @ 0xffffffff str r3, [sp, #8] /* Get the first dtd */ currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); ldr r3, [r2, #20] bic.w r3, r3, #31 /* In the next loop, USB_DeviceNotificationTrigger function may trigger a new transfer and the context always * keep in the critical section, so the Dtd sequence would still keep non-empty and the loop would be endless. * We set the Dtd's dtdInvalid in this while and add an if statement in the next loop so that this issue could * be fixed. */ while (NULL != currentDtd) sxth r1, r4 currentDtd = mov r4, r3 while (NULL != currentDtd) cbnz r4, } /* Save the original buffer address. */ if (NULL == message.buffer) { message.buffer = (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | ldr.w lr, [pc, #220] @ } /* Remove the dtd from the dtd in-used queue. */ if (ehciState->dtdHard[index] == ehciState->dtdTail[index]) { ehciState->dtdHard[index] = NULL; mov ip, r4 while (NULL != currentDtd) cbnz r3, (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); } if (NULL == currentDtd) { /* Set the QH to empty. */ ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; ldr r2, [r7, #8] add.w r2, r2, r1, lsl #6 movs r1, #1 str r1, [r2, #8] ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; str r3, [r2, #12] } OSA_EXIT_CRITICAL(); ldr r0, [sp, #0] bl if (0U != flag) cmp r4, #0 bne.n message.isSetup = 0U; (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); message.buffer = NULL; } return kStatus_USB_Success; movs r0, #0 } add sp, #16 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} currentDtd->reservedUnion.originalBufferInfo.dtdInvalid = 1U; ldrb r0, [r4, #31] orr.w r0, r0, #128 @ 0x80 strb r0, [r4, #31] currentDtd = (usb_device_ehci_dtd_struct_t *)(currentDtd->nextDtdPointer & USB_DEVICE_ECHI_DTD_POINTER_MASK); ldr r4, [r4, #0] bic.w r4, r4, #31 b.n if (0U == currentDtd->reservedUnion.originalBufferInfo.dtdInvalid) ldrsb.w r0, [r3, #31] cmp r0, #0 bge.n if (0U != (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) ldr r0, [r3, #4] lsls r0, r0, #24 bmi.n if (NULL == message.buffer) ldr r0, [sp, #4] cbnz r0, message.buffer = (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | ldr r0, [r3, #8] (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ldrh.w r8, [r3, #28] message.buffer = (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | and.w r0, r0, lr (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ubfx r8, r8, #0, #12 message.buffer = (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | orr.w r0, r0, r8 str r0, [sp, #4] if (ehciState->dtdHard[index] == ehciState->dtdTail[index]) ldr r0, [r2, #20] ldr.w r8, [r2, #76] @ 0x4c cmp r0, r8 ehciState->dtdHard[index] = (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer; iteet ne ldrne r0, [r0, #0] ehciState->dtdHard[index] = NULL; streq.w ip, [r2, #20] ehciState->dtdTail[index] = NULL; streq.w ip, [r2, #76] @ 0x4c ehciState->dtdHard[index] = (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer; strne r0, [r2, #20] if ((0U != currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) || ldr r0, [r3, #4] lsls r0, r0, #16 bmi.n ldr r0, [r2, #20] flag = 1; cmp r0, #31 it ls movls r4, #1 currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; ldr r0, [r7, #16] currentDtd->dtdTokenUnion.dtdToken = 0U; str.w ip, [r3, #4] currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; str r0, [r3, #0] ehciState->dtdFree = currentDtd; str r3, [r7, #16] ehciState->dtdCount++; ldrb.w r3, [r7, #132] @ 0x84 adds r3, #1 strb.w r3, [r7, #132] @ 0x84 (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & USB_DEVICE_ECHI_DTD_POINTER_MASK); ldr r3, [r2, #20] bic.w r3, r3, #31 b.n ehciState->registerBase->EPFLUSH |= primeBit; ldr r0, [r7, #4] ldr.w r8, [r0, #436] @ 0x1b4 orr.w r8, r8, r6 str.w r8, [r0, #436] @ 0x1b4 while (0U != (ehciState->registerBase->EPFLUSH & primeBit)) ldr.w r8, [r0, #436] @ 0x1b4 tst.w r8, r6 bne.n } while (0U != (ehciState->registerBase->EPSR & primeBit)); ldr.w r8, [r0, #440] @ 0x1b8 tst.w r8, r6 bne.n b.n flag = 1; movs r4, #1 b.n message.isSetup = 0U; movs r3, #0 (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r7, #0] message.code = ep; strb.w r5, [sp, #12] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); add r1, sp, #4 message.isSetup = 0U; strb.w r3, [sp, #13] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); bl message.buffer = NULL; b.n return kStatus_USB_InvalidHandle; movs r0, #3 b.n nop .word 0xfffff000 : 1UL << ((ep & USB_ENDPOINT_NUMBER_MASK) + ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U)); lsrs r2, r1, #3 { stmdb sp!, {r4, r5, r6, r7, r8, lr} 1UL << ((ep & USB_ENDPOINT_NUMBER_MASK) + ((ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U)); and.w r2, r2, #16 and.w r6, r1, #15 orrs r2, r6 uint32_t primeBit = movs r5, #1 ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; ldr r3, [r0, #8] uint32_t primeBit = lsls r5, r2 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction; lsls r2, r6, #1 ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; orr.w r2, r2, r1, lsr #7 add.w r3, r3, r2, lsl #6 mov.w r8, r2, lsl #6 ldrb.w r2, [r3, #56] @ 0x38 { mov r4, r0 ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 0U; bic.w r2, r2, #1 strb.w r2, [r3, #56] @ 0x38 uint8_t direction = lsrs r7, r1, #7 (void)USB_DeviceEhciCancel(ehciState, ep); bl if ((0U != (ehciState->registerBase->EPPRIME & primeBit)) || (0U != (ehciState->registerBase->EPSR & primeBit))) ldr r3, [r4, #4] ldr.w r2, [r3, #432] @ 0x1b0 tst r2, r5 bne.n ldr.w r2, [r3, #440] @ 0x1b8 ands r2, r5 bne.n ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristics = 0U; ldr r1, [r4, #8] str.w r2, [r1, r8] if (0U == endpoint) cbnz r6, ehciState->registerBase->EPCR[endpoint - 1U] &= ldr.w r2, [r3, #448] @ 0x1c0 ~((0U != direction) ? (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXT_MASK | USBHS_EPCR_TXS_MASK) : cmp r7, #0 ite eq mvneq.w r1, #141 @ 0x8d mvnne.w r1, #9240576 @ 0x8d0000 ehciState->registerBase->EPCR[endpoint - 1U] &= ands r2, r1 str.w r2, [r3, #448] @ 0x1c0 return kStatus_USB_Success; movs r0, #0 } ldmia.w sp!, {r4, r5, r6, r7, r8, pc} ehciState->registerBase->EPCR[endpoint - 1U] &= add.w r3, r3, r6, lsl #2 b.n return kStatus_USB_Busy; movs r0, #2 b.n : * @param param The param type is determined by the selected item. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceEhciControl(usb_device_controller_handle ehciHandle, usb_device_control_type_t type, void *param) { stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} mov r5, r1 mov r4, r2 #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U)) usb_device_struct_t *deviceHandle; uint64_t startTick; #endif if (NULL == ehciHandle) mov r6, r0 cmp r0, #0 beq.w #if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U)) deviceHandle = (usb_device_struct_t *)ehciState->deviceHandle; #endif switch (type) cmp r1, #20 bhi.w tbh [pc, r1, lsl #1] .short 0x0015 .word 0x00260020 .word 0x00bb00b3 .word 0x011400e6 .word 0x001c011a .word 0x01590159 .word 0x01590159 .word 0x013f0159 .word 0x01590152 .word 0x01590159 .word 0x01360159 { case kUSB_DeviceControlRun: ehciState->registerBase->USBCMD |= USBHS_USBCMD_RS_MASK; ldr r2, [r0, #4] ldr.w r3, [r2, #320] @ 0x140 orr.w r3, r3, #1 str.w r3, [r2, #320] @ 0x140 error = kStatus_USB_Success; break; case kUSB_DeviceControlStop: ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_RS_MASK; error = kStatus_USB_Success; movs r5, #0 /*no action*/ break; } return error; } mov r0, r5 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, pc} ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_RS_MASK; ldr r2, [r0, #4] ldr.w r3, [r2, #320] @ 0x140 bic.w r3, r3, #1 b.n if (NULL != param) cmp r2, #0 beq.w uint32_t primeBit = 1UL << ((epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK) + ldrb.w r9, [r2, #2] uint16_t maxPacketSize = epInit->maxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK; ldrh.w fp, [r2] uint8_t transferType = epInit->transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK; ldrb.w sl, [r2, #3] ((epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> 0x03U)); mov.w r3, r9, lsr #3 and.w r7, r9, #15 and.w r3, r3, #16 uint32_t primeBit = 1UL << ((epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK) + orrs r3, r7 mov.w r8, #1 (void)USB_DeviceEhciCancel(ehciState, epInit->endpointAddress); mov r1, r9 uint32_t primeBit = 1UL << ((epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK) + lsl.w r8, r8, r3 (void)USB_DeviceEhciCancel(ehciState, epInit->endpointAddress); bl if ((0U != (ehciState->registerBase->EPPRIME & primeBit)) || (0U != (ehciState->registerBase->EPSR & primeBit))) ldr r0, [r6, #4] ldr.w r3, [r0, #432] @ 0x1b0 tst.w r8, r3 bne.n ldr.w r3, [r0, #440] @ 0x1b8 ands.w r8, r8, r3 bne.n ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = ldr r2, [r6, #8] uint8_t transferType = epInit->transferType & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK; and.w r3, sl, #3 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction; lsls r1, r7, #1 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = orr.w r1, r1, r9, lsr #7 if (USB_ENDPOINT_ISOCHRONOUS == transferType) cmp r3, #1 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = mov.w r5, r1, lsl #6 uint16_t maxPacketSize = epInit->maxPacketSize & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK; ubfx lr, fp, #0, #11 uint8_t direction = (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) >> mov.w ip, r9, lsr #7 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = add.w r1, r2, r1, lsl #6 if (USB_ENDPOINT_ISOCHRONOUS == transferType) bne.n 1UL + ((((uint32_t)epInit->maxPacketSize) & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK) >> ldrh r6, [r4, #0] ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = ldr.w r8, [r2, r5] 1UL + ((((uint32_t)epInit->maxPacketSize) & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK) >> ubfx r6, r6, #11, #2 adds r6, #1 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = bfi r8, r6, #30, #2 if (maxPacketSize > USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE) cmp.w lr, #1024 @ 0x400 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = str.w r8, [r2, r5] if (maxPacketSize > USB_DEVICE_MAX_HS_ISO_MAX_PACKET_SIZE) it cs movcs.w lr, #1024 @ 0x400 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.maxPacketSize = ldr r6, [r2, r5] bfi r6, lr, #16, #11 str r6, [r2, r5] ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.zlt = epInit->zlt; ldrb.w r6, [r1, #56] @ 0x38 ldrb r4, [r4, #4] bfi r6, r4, #1, #1 strb.w r6, [r1, #56] @ 0x38 if ((USB_CONTROL_ENDPOINT == endpoint)) cbnz r7, ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = 1U; ldr r4, [r2, r5] orr.w r4, r4, #536870912 @ 0x20000000 str r4, [r2, r5] ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios = 1U; ldr r4, [r2, r5] orr.w r4, r4, #32768 @ 0x8000 str r4, [r2, r5] ehciState->registerBase->EPCR0 |= ldr.w r2, [r0, #448] @ 0x1c0 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : cmp.w ip, #0 bne.n (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXR_MASK | ((uint32_t)transferType << USBHS_EPCR_RXT_SHIFT))); lsls r3, r3, #2 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : orr.w r3, r3, #192 @ 0xc0 b.n ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.mult = 0U; ldr r6, [r2, r5] bfi r6, r8, #30, #2 str r6, [r2, r5] b.n ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = ldr r6, [r2, r5] ((0U == epInit->zlt) ? 1U : 0U); clz r4, r4 lsrs r4, r4, #5 ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = bfi r6, r4, #29, #1 str r6, [r2, r5] ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios = 0U; ldr r4, [r2, r5] bic.w r4, r4, #32768 @ 0x8000 str r4, [r2, r5] ehciState->registerBase->EPCR[endpoint - 1U] |= add.w r2, r0, r7, lsl #2 ldr.w r0, [r2, #448] @ 0x1c0 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : cmp.w ip, #0 bne.n (USBHS_EPCR_RXE_MASK | USBHS_EPCR_RXR_MASK | ((uint32_t)transferType << USBHS_EPCR_RXT_SHIFT))); lsls r3, r3, #2 (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : orr.w r3, r3, #192 @ 0xc0 b.n (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : lsls r3, r3, #18 orr.w r3, r3, #12582912 @ 0xc00000 ehciState->registerBase->EPCR0 |= orrs r3, r2 str.w r3, [r0, #448] @ 0x1c0 ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.isOpened = 1U; ldrb.w r3, [r1, #56] @ 0x38 orr.w r3, r3, #1 strb.w r3, [r1, #56] @ 0x38 return kStatus_USB_Success; b.n (USBHS_EPCR_TXE_MASK | USBHS_EPCR_TXR_MASK | ((uint32_t)transferType << USBHS_EPCR_TXT_SHIFT)) : lsls r3, r3, #18 orr.w r3, r3, #12582912 @ 0xc00000 ehciState->registerBase->EPCR[endpoint - 1U] |= orrs r3, r0 str.w r3, [r2, #448] @ 0x1c0 b.n if (NULL != param) cmp r2, #0 beq.w } ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, lr} error = USB_DeviceEhciEndpointDeinit(ehciState, *temp8); ldrb r1, [r2, #0] b.w if (NULL != param) cmp r2, #0 beq.w error = USB_DeviceEhciEndpointStall(ehciState, *temp8); ldrb r1, [r2, #0] uint8_t endpoint = ep & USB_ENDPOINT_NUMBER_MASK; and.w r4, r1, #15 uint8_t index = ((uint8_t)((uint32_t)endpoint << 1U)) | direction; lsls r5, r4, #1 orr.w r5, r5, r1, lsr #7 uint8_t direction = lsrs r7, r1, #7 if (0U != ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios) lsls r5, r5, #6 (void)USB_DeviceEhciCancel(ehciState, ep); bl if (0U != ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.ios) ldr r3, [r6, #8] ldr r3, [r3, r5] tst.w r3, #32768 @ 0x8000 ldr r3, [r6, #4] beq.n if (0U == endpoint) cbnz r4, ehciState->registerBase->EPCR[endpoint - 1U] |= (USBHS_EPCR_TXS_MASK | USBHS_EPCR_RXS_MASK); ldr.w r2, [r3, #448] @ 0x1c0 orr.w r2, r2, #65537 @ 0x10001 ehciState->registerBase->EPCR[endpoint - 1U] |= str.w r2, [r3, #448] @ 0x1c0 b.n ehciState->registerBase->EPCR[endpoint - 1U] |= (USBHS_EPCR_TXS_MASK | USBHS_EPCR_RXS_MASK); add.w r3, r3, r4, lsl #2 b.n if (0U == endpoint) cbnz r4, ((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK); cmp r7, #0 ehciState->registerBase->EPCR[endpoint - 1U] |= ldr.w r2, [r3, #448] @ 0x1c0 ((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK); ite eq moveq r1, #1 movne.w r1, #65536 @ 0x10000 ehciState->registerBase->EPCR[endpoint - 1U] |= orrs r2, r1 b.n add.w r3, r3, r4, lsl #2 b.n if (NULL != param) cmp r2, #0 beq.n error = USB_DeviceEhciEndpointUnstall(ehciState, *temp8); ldrb r1, [r2, #0] ehciState->registerBase->USBCMD |= USBHS_USBCMD_RS_MASK; ldr r3, [r6, #4] if (0U == endpoint) ands.w r2, r1, #15 uint8_t direction = mov.w r0, r1, lsr #7 if (0U == endpoint) bne.n ehciState->registerBase->EPCR0 &= ~((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK); cmp r0, #0 ldr.w r2, [r3, #448] @ 0x1c0 ite eq mvneq.w r0, #1 mvnne.w r0, #65536 @ 0x10000 ands r2, r0 ehciState->registerBase->EPCR[endpoint - 1U] |= ((0U != direction) ? USBHS_EPCR_TXR_MASK : USBHS_EPCR_RXR_MASK); str.w r2, [r3, #448] @ 0x1c0 (void)USB_DeviceEhciCancel(ehciState, ep); mov r0, r6 bl return kStatus_USB_Success; b.n ehciState->registerBase->EPCR[endpoint - 1U] &= add.w r3, r3, r2, lsl #2 ~((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK); cmp r0, #0 ehciState->registerBase->EPCR[endpoint - 1U] &= ldr.w r2, [r3, #448] @ 0x1c0 ~((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK); ite eq mvneq.w r0, #1 mvnne.w r0, #65536 @ 0x10000 ehciState->registerBase->EPCR[endpoint - 1U] &= and.w r2, r2, r0 str.w r2, [r3, #448] @ 0x1c0 ehciState->registerBase->EPCR[endpoint - 1U] |= ((0U != direction) ? USBHS_EPCR_TXR_MASK : USBHS_EPCR_RXR_MASK); ldr.w r2, [r3, #448] @ 0x1c0 ite eq moveq r0, #64 @ 0x40 movne.w r0, #4194304 @ 0x400000 orrs r2, r0 b.n if (NULL != param) movs r5, #1 cmp r2, #0 beq.w *temp16 = ((uint16_t)USB_DEVICE_CONFIG_SELF_POWER strh r5, [r2, #0] error = kStatus_USB_Success; b.n if (NULL != param) cmp r2, #0 beq.n uint8_t ep = (endpointStatus->endpointAddress) & USB_ENDPOINT_NUMBER_MASK; ldrb r3, [r2, #0] and.w r2, r3, #15 if (ep < USB_DEVICE_CONFIG_ENDPOINTS) cmp r2, #6 bhi.n ehciState->registerBase->USBCMD |= USBHS_USBCMD_RS_MASK; ldr r1, [r0, #4] uint8_t direction = lsrs r3, r3, #7 if (0U != ep) cbz r2, (0U != (ehciState->registerBase->EPCR[ep - 1U] & adds r2, #111 @ 0x6f add.w r1, r1, r2, lsl #2 ldr r2, [r1, #4] ((0U != direction) ? USBHS_EPCR_TXS_MASK : USBHS_EPCR_RXS_MASK))) ? cmp r3, #0 ite eq moveq r3, #1 movne.w r3, #65536 @ 0x10000 (uint16_t)kUSB_DeviceEndpointStateStalled : tst r2, r3 ite ne movne r3, #1 moveq r3, #0 endpointStatus->endpointStatus = strh r3, [r4, #2] b.n (0U != (ehciState->registerBase->EPCR0 & ldr.w r2, [r1, #448] @ 0x1c0 b.n if (NULL != param) cbz r2, ((((uint32_t)(*temp8)) << USBHS_DEVICEADDR_USBADR_SHIFT) | USBHS_DEVICEADDR_USBADRA_MASK); ldrb r3, [r4, #0] ehciState->registerBase->DEVICEADDR = ldr r2, [r0, #4] ((((uint32_t)(*temp8)) << USBHS_DEVICEADDR_USBADR_SHIFT) | USBHS_DEVICEADDR_USBADRA_MASK); lsls r3, r3, #25 orr.w r3, r3, #16777216 @ 0x1000000 ehciState->registerBase->DEVICEADDR = str.w r3, [r2, #340] @ 0x154 error = kStatus_USB_Success; b.n switch (type) movs r4, #0 (void)USB_DeviceEhciEndpointDeinit(ehciState, (count | (USB_IN << 0x07U))); orn r1, r4, #127 @ 0x7f uxtb r5, r4 uxtb r1, r1 mov r0, r6 bl for (uint8_t count = 0U; count < USB_DEVICE_CONFIG_ENDPOINTS; count++) adds r4, #1 (void)USB_DeviceEhciEndpointDeinit(ehciState, (count | (USB_OUT << 0x07U))); mov r1, r5 mov r0, r6 bl for (uint8_t count = 0U; count < USB_DEVICE_CONFIG_ENDPOINTS; count++) cmp r4, #7 bne.n USB_DeviceEhciSetDefaultState(ehciState); mov r0, r6 bl break; b.n if (NULL != param) cbz r2, *temp8 = ehciState->speed; ldrb.w r3, [r0, #136] @ 0x88 strb r3, [r2, #0] error = kStatus_USB_Success; b.n return kStatus_USB_InvalidHandle; movs r5, #3 b.n usb_status_t error = kStatus_USB_Error; movs r5, #1 b.n : * * @param deviceHandle The device handle got from USB_DeviceInit. * */ void USB_DeviceEhciIsrFunction(void *deviceHandle) { stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} sub sp, #36 @ 0x24 usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle; usb_device_ehci_state_struct_t *ehciState; uint32_t status; if (NULL == deviceHandle) cmp r0, #0 beq.n { return; } ehciState = (usb_device_ehci_state_struct_t *)(handle->controllerHandle); ldr r4, [r0, #8] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); } } #endif /* USB_DEVICE_CONFIG_DETACH_ENABLE */ status = ehciState->registerBase->USBSTS; ldr r3, [r4, #4] ldr.w r1, [r3, #324] @ 0x144 status &= ehciState->registerBase->USBINTR; ldr.w r2, [r3, #328] @ 0x148 and.w sl, r1, r2 /* Error interrupt */ USB_DeviceEhciInterruptError(ehciState); } #endif /* USB_DEVICE_CONFIG_ERROR_HANDLING */ if (0U != (status & USBHS_USBSTS_URI_MASK)) tst.w sl, #64 @ 0x40 ehciState->registerBase->USBSTS = status; str.w sl, [r3, #324] @ 0x144 if (0U != (status & USBHS_USBSTS_URI_MASK)) beq.n status = ehciState->registerBase->EPSETUPSR; ldr.w r2, [r3, #428] @ 0x1ac ehciState->registerBase->EPSETUPSR = status; str.w r2, [r3, #428] @ 0x1ac status = ehciState->registerBase->EPCOMPLETE; ldr.w r2, [r3, #444] @ 0x1bc ehciState->registerBase->EPCOMPLETE = status; str.w r2, [r3, #444] @ 0x1bc ehciState->registerBase->EPFLUSH = USBHS_EPFLUSH_FERB_MASK | USBHS_EPFLUSH_FETB_MASK; mov.w r1, #16711935 @ 0xff00ff str.w r1, [r3, #436] @ 0x1b4 } while (0U != (ehciState->registerBase->EPPRIME & (USBHS_EPPRIME_PERB_MASK | USBHS_EPPRIME_PETB_MASK))); ldr.w r2, [r3, #432] @ 0x1b0 tst.w r2, #16711935 @ 0xff00ff bne.n if (0U != (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) ldr.w r3, [r3, #388] @ 0x184 ands.w r3, r3, #256 @ 0x100 beq.n ehciState->isResetting = 1U; movs r3, #1 strb.w r3, [r4, #134] @ 0x86 { /* Reset interrupt */ USB_DeviceEhciInterruptReset(ehciState); } if (0U != (status & USBHS_USBSTS_UI_MASK)) tst.w sl, #1 beq.n status = ehciState->registerBase->EPSETUPSR; ldr r3, [r4, #4] ldr.w r6, [r3, #428] @ 0x1ac if (0U != status) cmp r6, #0 bne.n status = ehciState->registerBase->EPCOMPLETE; ldr r3, [r4, #4] ldr.w fp, [r3, #444] @ 0x1bc ehciState->registerBase->EPCOMPLETE = status; str.w fp, [r3, #444] @ 0x1bc if (0U != status) cmp.w fp, #0 bne.n { /* Token done interrupt */ USB_DeviceEhciInterruptTokenDone(ehciState); } if (0U != (status & USBHS_USBSTS_PCI_MASK)) tst.w sl, #4 beq.n message.buffer = (uint8_t *)NULL; movs r3, #0 message.isSetup = 0U; strb.w r3, [sp, #29] if (0U == (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) ldr r2, [r4, #4] message.buffer = (uint8_t *)NULL; str r3, [sp, #20] if (0U == (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) ldr.w r5, [r2, #388] @ 0x184 message.length = 0U; str r3, [sp, #24] if (0U == (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_PR_MASK)) ands.w r5, r5, #256 @ 0x100 bne.n if (0U != (ehciState->registerBase->PORTSC1 & USBHS_PORTSC1_HSP_MASK)) ldr.w r3, [r2, #388] @ 0x184 ubfx r3, r3, #9, #1 lsls r3, r3, #1 strb.w r3, [r4, #136] @ 0x88 if (0U != ehciState->isResetting) ldrb.w r3, [r4, #134] @ 0x86 cbz r3, message.code = (uint8_t)kUSB_DeviceNotifyBusReset; movs r3, #16 strb.w r3, [sp, #28] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r4, #0] add r1, sp, #20 bl ehciState->isResetting = 0U; strb.w r5, [r4, #134] @ 0x86 if (0U != (status & USBHS_USBSTS_SRI_MASK)) { /* Sof interrupt */ USB_DeviceEhciInterruptSof(ehciState); } } add sp, #36 @ 0x24 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc} message.buffer = (uint8_t *)NULL; str r3, [sp, #20] message.length = 0U; str r3, [sp, #24] message.code = (uint8_t)kUSB_DeviceNotifyBusReset; movs r3, #16 strh.w r3, [sp, #28] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r4, #0] add r1, sp, #20 bl b.n movs r5, #0 message.isSetup = 1U; movs r7, #1 if (0U != (status & (1UL << endpoint))) lsr.w r3, r6, r5 lsls r0, r3, #31 bpl.n temp = (void *)&ehciState->qh[(uint8_t)((uint32_t)endpoint << 1U) + USB_OUT].setupBufferBack; ldr r3, [r4, #8] direction = (deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_IN) >> USB_REQUEST_TYPE_DIR_SHIFT; add.w fp, r3, r5, lsl #7 uxtb r1, r5 ldrb.w r2, [fp, #48]! USB_DeviceEhciCancelControlPipe(ehciState, endpoint, direction); mov r0, r4 direction = (deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_IN) >> USB_REQUEST_TYPE_DIR_SHIFT; lsrs r2, r2, #7 USB_DeviceEhciCancelControlPipe(ehciState, endpoint, direction); mov r8, r1 str r2, [sp, #4] bl USB_DeviceEhciCancelControlPipe(ehciState, endpoint, 1U ^ direction); ldr r2, [sp, #4] mov r0, r4 eor.w r2, r2, #1 mov r1, r8 bl message.code = (endpoint) | (USB_OUT << 0x07U); strb.w r8, [sp, #28] message.isSetup = 1U; strb.w r7, [sp, #29] message.length = USB_SETUP_PACKET_SIZE; movs r3, #8 str r3, [sp, #24] ehciState->registerBase->EPSETUPSR = 1UL << ep; ldr r3, [r4, #4] message.buffer = (uint8_t *)deviceSetup; str.w fp, [sp, #20] ehciState->registerBase->EPSETUPSR = 1UL << ep; lsl.w r2, r7, r5 str.w r2, [r3, #428] @ 0x1ac ehciState->qh[index].setupBufferBack[0] = ehciState->qh[index].setupBuffer[0]; ldr r2, [r4, #8] mov.w r9, r5, lsl #7 add r2, r9 ldr r0, [r2, #40] @ 0x28 ehciState->qh[index].setupBufferBack[1] = ehciState->qh[index].setupBuffer[1]; ldr.w ip, [r2, #44] @ 0x2c ehciState->registerBase->USBCMD |= USBHS_USBCMD_SUTW_MASK; ldr.w r1, [r3, #320] @ 0x140 orr.w r1, r1, #8192 @ 0x2000 str.w r1, [r3, #320] @ 0x140 if (0U != (ehciState->registerBase->USBCMD & USBHS_USBCMD_SUTW_MASK)) ldr.w r1, [r3, #320] @ 0x140 lsls r1, r1, #18 bpl.n str r0, [r2, #48] @ 0x30 str.w ip, [r2, #52] @ 0x34 ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_SUTW_MASK; ldr.w r2, [r3, #320] @ 0x140 (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r4, #0] ehciState->registerBase->USBCMD &= ~USBHS_USBCMD_SUTW_MASK; bic.w r2, r2, #8192 @ 0x2000 str.w r2, [r3, #320] @ 0x140 (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); add r1, sp, #20 bl for (endpoint = 0U; endpoint < USB_DEVICE_CONFIG_ENDPOINTS; endpoint++) adds r5, #1 cmp r5, #7 bne.n b.n mov.w r9, #0 message.buffer = NULL; mov r6, r9 if (0U != (status & (1UL << count))) lsr.w r3, fp, r9 lsls r1, r3, #31 bmi.n for (count = 0U; count < 32U; count++) add.w r9, r9, #1 cmp.w r9, #32 bne.n b.n if (count > 15U) cmp.w r9, #15 uxtb.w r1, r9 endpoint = count - 16U; ittte hi subhi r1, #16 uxtbhi r1, r1 direction = USB_IN; movhi r5, #1 direction = USB_OUT; movls r5, #0 if (endpoint >= USB_DEVICE_CONFIG_ENDPOINTS) cmp r1, #6 bhi.n index = (endpoint << 1U) + direction; add.w r0, r5, r1, lsl #1 uxtb r0, r0 message.buffer = NULL; str r6, [sp, #20] message.length = 0U; str r6, [sp, #24] if ((USB_CONTROL_ENDPOINT == endpoint) && (USB_IN == direction)) cbnz r1, cbz r5, if (1U == ehciState->qh[index].endpointStatusUnion.endpointStatusBitmap.zlt) ldr r3, [r4, #8] ldrb.w r7, [r3, #120] @ 0x78 lsls r2, r7, #30 bpl.n ehciState->qh[index].capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt) ldr r7, [r3, #64] @ 0x40 if (0U == lsls r7, r7, #2 .capabilttiesCharacteristicsUnion.capabilttiesCharacteristicsBitmap.zlt = 1U; ittt pl ldrpl r7, [r3, #64] @ 0x40 orrpl.w r7, r7, #536870912 @ 0x20000000 strpl r7, [r3, #64] @ 0x40 ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; sxth r3, r0 str r3, [sp, #8] lsls r3, r0, #6 currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & add.w r0, r4, r0, lsl #2 message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); orr.w r2, r1, r5, lsl #7 primeBit = 1UL << (endpoint + 16U * direction); movs r7, #1 add.w r1, r1, r5, lsl #4 lsls r7, r1 currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & ldr r1, [r0, #20] message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); str r2, [sp, #4] while (NULL != currentDtd) bics.w r2, r1, #31 beq.n currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & ldr r2, [sp, #8] add.w r8, r4, r2, lsl #2 ldr.w r0, [r8, #20] bic.w r0, r0, #31 mov r5, r0 mov r1, r0 while (NULL != currentDtd) cbz r1, (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) || ldr r2, [r1, #4] if ((0U != lsls r2, r2, #24 bmi.n (0U != currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc)) ldr r2, [r1, #4] (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) || lsls r2, r2, #16 bpl.n if ((0U == (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & ldr r2, [r1, #4] lsls r2, r2, #24 bmi.n (0U != currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc)) ldr r1, [r1, #4] USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) && lsls r2, r1, #16 bpl.n while (NULL != currentDtd) cmp r0, #0 beq.n if (0U != (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & USB_DEVICE_ECHI_DTD_STATUS_ACTIVE)) ldr r1, [r5, #4] lsls r0, r1, #24 bmi.n if (NULL == message.buffer) ldr r1, [sp, #20] cbnz r1, (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | ldr r1, [r5, #8] (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ldrh r0, [r5, #28] (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | bfc r1, #0, #12 (currentDtd->reservedUnion.originalBufferInfo.originalBufferOffest)); ubfx r0, r0, #0, #12 (uint8_t *)((currentDtd->bufferPointerPage[0] & USB_DEVICE_ECHI_DTD_PAGE_MASK) | orrs r1, r0 message.buffer = str r1, [sp, #20] currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes); ldr r0, [r5, #4] message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength - ldr r1, [r5, #28] currentDtd->dtdTokenUnion.dtdTokenBitmap.totalBytes); ubfx r0, r0, #16, #15 message.length += (currentDtd->reservedUnion.originalBufferInfo.originalBufferLength - ubfx r1, r1, #12, #19 subs r1, r1, r0 ldr r0, [sp, #24] add r0, r1 str r0, [sp, #24] if (ehciState->dtdHard[index] == ehciState->dtdTail[index]) ldr.w r1, [r8, #20] ldr.w r0, [r8, #76] @ 0x4c cmp r1, r0 bne.n ehciState->dtdHard[index] = NULL; str.w r6, [r8, #20] ehciState->dtdTail[index] = NULL; str.w r6, [r8, #76] @ 0x4c ehciState->qh[index].nextDtdPointer = USB_DEVICE_ECHI_DTD_TERMINATE_MASK; ldr r1, [r4, #8] add r1, r3 movs r0, #1 str r0, [r1, #8] ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; str r6, [r1, #12] if ((0U != currentDtd->dtdTokenUnion.dtdTokenBitmap.ioc) || ldr r1, [r5, #4] lsls r1, r1, #16 bmi.n ldr.w r1, [r8, #20] cmp r1, #31 bhi.n str r3, [sp, #12] message.code = endpoint | (uint8_t)((uint32_t)direction << 0x07U); ldr r3, [sp, #4] strb.w r3, [sp, #28] message.isSetup = 0U; strb.w r6, [sp, #29] (void)USB_DeviceNotificationTrigger(ehciState->deviceHandle, &message); ldr r0, [r4, #0] add r1, sp, #20 bl message.length = 0U; ldr r3, [sp, #12] message.buffer = NULL; str r6, [sp, #20] message.length = 0U; str r6, [sp, #24] currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; ldr r1, [r4, #16] currentDtd->dtdTokenUnion.dtdToken = 0U; str r6, [r5, #4] currentDtd->nextDtdPointer = (uint32_t)ehciState->dtdFree; str r1, [r5, #0] ehciState->dtdCount++; ldrb.w r1, [r4, #132] @ 0x84 ehciState->dtdFree = currentDtd; str r5, [r4, #16] ehciState->dtdCount++; adds r1, #1 strb.w r1, [r4, #132] @ 0x84 currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & ldr.w r5, [r8, #20] if ((NULL != currentDtd) && (0U != (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & cmp r5, #31 bls.w currentDtd = (usb_device_ehci_dtd_struct_t *)((uint32_t)ehciState->dtdHard[index] & bic.w r5, r5, #31 if ((NULL != currentDtd) && (0U != (currentDtd->dtdTokenUnion.dtdTokenBitmap.status & ldr r1, [r5, #4] lsls r2, r1, #24 bpl.n ehciState->registerBase->EPPRIME = primeBit; ldr r1, [r4, #4] str.w r7, [r1, #432] @ 0x1b0 if (0U == (ehciState->registerBase->EPSR & primeBit)) ldr.w r0, [r1, #440] @ 0x1b8 tst r7, r0 bne.n while (0U != (ehciState->registerBase->EPPRIME & primeBit)) ldr.w r0, [r1, #432] @ 0x1b0 tst r7, r0 bne.n if (0U == (ehciState->registerBase->EPSR & primeBit)) ldr.w r2, [r1, #440] @ 0x1b8 ands r2, r7 bne.n ehciState->qh[index].nextDtdPointer = (uint32_t)currentDtd; ldr r0, [r4, #8] add r0, r3 str r5, [r0, #8] ehciState->qh[index].dtdTokenUnion.dtdToken = 0U; str r2, [r0, #12] ehciState->registerBase->EPPRIME = primeBit; str.w r7, [r1, #432] @ 0x1b0 while (NULL != currentDtd) b.n currentDtd = (usb_device_ehci_dtd_struct_t *)(currentDtd->nextDtdPointer & ldr r1, [r1, #0] bic.w r1, r1, #31 b.n (usb_device_ehci_dtd_struct_t *)ehciState->dtdHard[index]->nextDtdPointer; ldr r1, [r1, #0] ehciState->dtdHard[index] = str.w r1, [r8, #20] b.n ... : #include "fsl_device_registers.h" #include "usb_phy.h" void *USB_EhciPhyGetBase(uint8_t controllerId) { push {r4, r5, lr} void *usbPhyBase = NULL; #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) uint32_t instance; uint32_t newinstance = 0; uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS; ldr r3, [pc, #104] @ () { mov r5, r0 uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS; ldmia.w r3, {r0, r1, r2} { sub sp, #28 uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS; mov r4, sp uint32_t usbphy_base[] = USBPHY_BASE_ADDRS; add r3, sp, #24 uint32_t *temp; if (controllerId < (uint8_t)kUSB_ControllerEhci0) cmp r5, #1 uint32_t usbphy_base_temp[] = USBPHY_BASE_ADDRS; stmia.w r4, {r0, r1, r2} uint32_t usbphy_base[] = USBPHY_BASE_ADDRS; stmdb r3, {r0, r1, r2} if (controllerId < (uint8_t)kUSB_ControllerEhci0) bhi.n { return NULL; movs r0, #0 } temp = (uint32_t *)usbphy_base[controllerId]; usbPhyBase = (void *)temp; #endif return usbPhyBase; } add sp, #28 pop {r4, r5, pc} if ((controllerId == (uint8_t)kUSB_ControllerEhci0) || (controllerId == (uint8_t)kUSB_ControllerEhci1)) subs r3, r5, #2 uxtb r3, r3 cmp r3, #1 bls.n else if ((controllerId == (uint8_t)kUSB_ControllerLpcIp3511Hs0) || subs r3, r5, #6 uxtb r3, r3 cmp r3, #1 bls.n else if ((controllerId == (uint8_t)kUSB_ControllerIp3516Hs0) || (controllerId == (uint8_t)kUSB_ControllerIp3516Hs1)) sub.w r3, r5, #10 uxtb r3, r3 cmp r3, #1 it hi movhi r3, r5 uint32_t newinstance = 0; movs r2, #0 for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++) mov r1, r2 if (0U != usbphy_base_temp[instance]) ldr.w r0, [r4], #4 cbz r0, usbphy_base[newinstance++] = usbphy_base_temp[instance]; add r5, sp, #24 add.w r5, r5, r2, lsl #2 adds r2, #1 str.w r0, [r5, #-12] for (instance = 0; instance < (sizeof(usbphy_base_temp) / sizeof(usbphy_base_temp[0])); instance++) adds r1, #1 cmp r1, #3 bne.n if (controllerId > newinstance) cmp r3, r2 bhi.n temp = (uint32_t *)usbphy_base[controllerId]; add r2, sp, #24 add.w r3, r2, r3, lsl #2 ldr.w r0, [r3, #-12] return usbPhyBase; b.n nop .word 0x60008a08 : * * @retval kStatus_USB_Success cancel successfully. * @retval kStatus_USB_Error the freq value is incorrect. */ uint32_t USB_EhciPhyInit(uint8_t controllerId, uint32_t freq, usb_phy_config_struct_t *phyConfig) { push {r3, r4, r5, lr} mov r4, r0 mov r5, r2 #if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) USBPHY_Type *usbPhyBase; usbPhyBase = (USBPHY_Type *)USB_EhciPhyGetBase(controllerId); bl if (NULL == usbPhyBase) cmp r0, #0 beq.n ANATOP->HW_ANADIG_USB2_CHRG_DETECT.SET = ANATOP_HW_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B_MASK | ANATOP_HW_ANADIG_USB2_CHRG_DETECT_EN_B_MASK; #endif #if (defined USB_ANALOG) USB_ANALOG->INSTANCE[controllerId - (uint8_t)kUSB_ControllerEhci0].CHRG_DETECT_SET = movs r2, #96 @ 0x60 subs r3, r4, #2 muls r3, r2 add.w r3, r3, #1073741824 @ 0x40000000 add.w r3, r3, #884736 @ 0xd8000 mov.w r2, #1572864 @ 0x180000 str.w r2, [r3, #436] @ 0x1b4 #if ((!(defined FSL_FEATURE_SOC_CCM_ANALOG_COUNT)) && (!(defined FSL_FEATURE_SOC_ANATOP_COUNT))) usbPhyBase->TRIM_OVERRIDE_EN = 0x001fU; /* override IFR value */ #endif usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL2_MASK; /* support LS device. */ ldr r3, [r0, #48] @ 0x30 orr.w r3, r3, #16384 @ 0x4000 str r3, [r0, #48] @ 0x30 usbPhyBase->CTRL |= USBPHY_CTRL_SET_ENUTMILEVEL3_MASK; /* support external FS Hub with LS device connected. */ ldr r3, [r0, #48] @ 0x30 orr.w r3, r3, #32768 @ 0x8000 str r3, [r0, #48] @ 0x30 /* PWD register provides overall control of the PHY power state */ usbPhyBase->PWD = 0U; movs r3, #0 str r3, [r0, #0] if (((uint8_t)kUSB_ControllerIp3516Hs0 == controllerId) || ((uint8_t)kUSB_ControllerIp3516Hs1 == controllerId) || sub.w r3, r4, #10 cmp r3, #1 bls.n subs r4, #6 cmp r4, #1 bhi.n ((uint8_t)kUSB_ControllerLpcIp3511Hs0 == controllerId) || ((uint8_t)kUSB_ControllerLpcIp3511Hs1 == controllerId)) { usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_CLKGATE_MASK; mov.w r3, #524288 @ 0x80000 str r3, [r0, #52] @ 0x34 usbPhyBase->CTRL_SET = USBPHY_CTRL_SET_ENAUTOCLR_PHY_PWD_MASK; mov.w r3, #1048576 @ 0x100000 str r3, [r0, #52] @ 0x34 } if (NULL != phyConfig) cbnz r5, (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) | USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM))); } #endif return (uint8_t)kStatus_USB_Success; movs r0, #0 } pop {r3, r4, r5, pc} (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) | ldrb r3, [r5, #1] USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM))); ldrb r1, [r5, #2] ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) | ldr r2, [r0, #16] (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) | lsls r3, r3, #16 USBPHY_TX_TXCAL45DM(phyConfig->TXCAL45DM))); lsls r1, r1, #8 and.w r1, r1, #3840 @ 0xf00 (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) | and.w r3, r3, #983040 @ 0xf0000 orrs r3, r1 ldrb r1, [r5, #0] ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) | bic.w r2, r2, #983055 @ 0xf000f (USBPHY_TX_D_CAL(phyConfig->D_CAL) | USBPHY_TX_TXCAL45DP(phyConfig->TXCAL45DP) | and.w r1, r1, #15 orrs r3, r1 ((usbPhyBase->TX & (~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK))) | bic.w r2, r2, #3840 @ 0xf00 orrs r3, r2 usbPhyBase->TX = str r3, [r0, #16] b.n return (uint8_t)kStatus_USB_Error; movs r0, #1 b.n : __ASM volatile ("MRS %0, primask" : "=r" (result) :: "memory"); mrs r3, PRIMASK __ASM volatile ("cpsid i" : : : "memory"); cpsid i free(p); } void OSA_EnterCritical(uint32_t *sr) { *sr = DisableGlobalIRQ(); str r3, [r0, #0] } bx lr : __ASM volatile ("MSR primask, %0" : : "r" (priMask) : "memory"); msr PRIMASK, r0 void OSA_ExitCritical(uint32_t sr) { EnableGlobalIRQ(sr); } bx lr : push {r3, lr} movs r0, #6 bl movs r0, #1 bl <_exit> <__assert_func>: push {r0, r1, r2, r3, r4, lr} mov r4, r2 mov r2, r3 ldr r3, [pc, #36] @ (<__assert_func+0x2c>) ldr r3, [r3, #0] mov r5, r0 ldr r0, [r3, #12] cbz r4, <__assert_func+0x24> ldr r3, [pc, #28] @ (<__assert_func+0x30>) str r1, [sp, #0] strd r3, r4, [sp, #4] ldr r1, [pc, #24] @ (<__assert_func+0x34>) mov r3, r5 bl bl ldr r3, [pc, #16] @ (<__assert_func+0x38>) mov r4, r3 b.n <__assert_func+0x12> nop .word 0x20000cd8 .word 0x60008f12 .word 0x60008f1f .word 0x60008f4d : ldr r3, [pc, #8] @ () mov r1, r0 ldr r0, [r3, #0] b.w <_malloc_r> nop .word 0x20000cd8 : push {r4, r5, r6, lr} ldr r6, [pc, #60] @ () mov r4, r1 ldr r1, [r6, #0] mov r5, r0 cbnz r1, bl <_sbrk_r> str r0, [r6, #0] mov r1, r4 mov r0, r5 bl <_sbrk_r> adds r3, r0, #1 bne.n mov.w r4, #4294967295 @ 0xffffffff mov r0, r4 pop {r4, r5, r6, pc} adds r4, r0, #3 bic.w r4, r4, #3 cmp r0, r4 beq.n subs r1, r4, r0 mov r0, r5 bl <_sbrk_r> adds r0, #1 bne.n b.n nop .word 0x20001f00 <_malloc_r>: stmdb sp!, {r4, r5, r6, r7, r8, lr} adds r5, r1, #3 bic.w r5, r5, #3 adds r5, #8 cmp r5, #12 it cc movcc r5, #12 cmp r5, #0 mov r6, r0 blt.n <_malloc_r+0x1c> cmp r1, r5 bls.n <_malloc_r+0x26> movs r3, #12 str r3, [r6, #0] movs r0, #0 ldmia.w sp!, {r4, r5, r6, r7, r8, pc} ldr r7, [pc, #196] @ (<_malloc_r+0xec>) bl <__malloc_lock> ldr r3, [r7, #0] mov r4, r3 cbnz r4, <_malloc_r+0x84> mov r1, r5 mov r0, r6 bl adds r3, r0, #1 mov r4, r0 bne.n <_malloc_r+0xe2> ldr r4, [r7, #0] mov r1, r4 cmp r1, #0 bne.n <_malloc_r+0xcc> cmp r4, #0 beq.n <_malloc_r+0xd6> ldr r3, [r4, #0] mov r0, r6 add.w r8, r4, r3 bl <_sbrk_r> cmp r8, r0 bne.n <_malloc_r+0xd6> ldr r1, [r4, #0] subs r5, r5, r1 mov r1, r5 mov r0, r6 bl adds r0, #1 beq.n <_malloc_r+0xd6> ldr r3, [r4, #0] add r3, r5 str r3, [r4, #0] ldr r3, [r7, #0] cmp r3, #0 beq.n <_malloc_r+0xe6> ldr r2, [r3, #4] cmp r2, r4 bne.n <_malloc_r+0xd2> movs r2, #0 str r2, [r3, #4] b.n <_malloc_r+0xa2> ldr r2, [r4, #0] subs r2, r2, r5 bmi.n <_malloc_r+0xc6> cmp r2, #11 bls.n <_malloc_r+0xbc> adds r1, r4, r5 cmp r3, r4 str r5, [r4, #0] it ne strne r1, [r3, #4] ldr r3, [r4, #4] it eq streq r1, [r7, #0] str r2, [r4, r5] str r3, [r1, #4] mov r0, r6 bl <__malloc_unlock> add.w r0, r4, #11 adds r3, r4, #4 bic.w r0, r0, #7 subs r2, r0, r3 beq.n <_malloc_r+0x22> subs r3, r3, r0 str r3, [r4, r2] b.n <_malloc_r+0x22> cmp r3, r4 ldr r2, [r4, #4] bne.n <_malloc_r+0x80> str r2, [r7, #0] b.n <_malloc_r+0xa2> mov r3, r4 ldr r4, [r4, #4] b.n <_malloc_r+0x30> mov r4, r1 ldr r1, [r1, #4] b.n <_malloc_r+0x44> mov r3, r2 b.n <_malloc_r+0x74> movs r3, #12 str r3, [r6, #0] mov r0, r6 bl <__malloc_unlock> b.n <_malloc_r+0x20> str r5, [r0, #0] b.n <_malloc_r+0xa2> str r3, [r3, #4] udf #255 @ 0xff nop .word 0x20001f04 <__malloc_lock>: bx lr <__malloc_unlock>: bx lr : push {r1, r2, r3} push {r0, r1, lr} mov r1, r0 add r3, sp, #12 ldr r0, [pc, #20] @ () ldr.w r2, [r3], #4 ldr r0, [r0, #0] str r3, [sp, #4] bl <_vfiprintf_r> add sp, #8 ldr.w lr, [sp], #4 add sp, #12 bx lr .word 0x20000cd8 : push {r4, lr} subs r1, #1 add r2, r0 cmp r0, r2 bne.n movs r0, #0 b.n ldrb r3, [r0, #0] ldrb.w r4, [r1, #1]! cmp r3, r4 beq.n subs r0, r3, r4 pop {r4, pc} adds r0, #1 b.n : add r2, r0 mov r3, r0 cmp r3, r2 bne.n bx lr strb.w r1, [r3], #1 b.n <_raise_r>: cmp r1, #31 push {r3, r4, r5, lr} mov r5, r0 mov r4, r1 bls.n <_raise_r+0x14> movs r3, #22 str r3, [r0, #0] mov.w r0, #4294967295 @ 0xffffffff pop {r3, r4, r5, pc} ldr r2, [r0, #60] @ 0x3c cbz r2, <_raise_r+0x1e> ldr.w r3, [r2, r1, lsl #2] cbnz r3, <_raise_r+0x32> mov r0, r5 bl <_getpid_r> mov r2, r4 mov r1, r0 mov r0, r5 ldmia.w sp!, {r3, r4, r5, lr} b.w <_kill_r> cmp r3, #1 beq.n <_raise_r+0x4c> adds r1, r3, #1 bne.n <_raise_r+0x42> movs r3, #22 str r3, [r0, #0] movs r0, #1 b.n <_raise_r+0x12> movs r1, #0 str.w r1, [r2, r4, lsl #2] mov r0, r4 blx r3 movs r0, #0 b.n <_raise_r+0x12> : ldr r3, [pc, #8] @ () mov r1, r0 ldr r0, [r3, #0] b.w <_raise_r> nop .word 0x20000cd8 <_kill_r>: push {r3, r4, r5, lr} ldr r5, [pc, #28] @ (<_kill_r+0x20>) movs r3, #0 mov r4, r0 mov r0, r1 mov r1, r2 str r3, [r5, #0] bl <_kill> adds r3, r0, #1 bne.n <_kill_r+0x1c> ldr r3, [r5, #0] cbz r3, <_kill_r+0x1c> str r3, [r4, #0] pop {r3, r4, r5, pc} nop .word 0x20002044 <_getpid_r>: b.w <_getpid> : add r2, r1 cmp r1, r2 add.w r3, r0, #4294967295 @ 0xffffffff bne.n bx lr push {r4, lr} ldrb.w r4, [r1], #1 strb.w r4, [r3, #1]! cmp r1, r2 bne.n pop {r4, pc} <_free_r>: push {r3, r4, r5, lr} mov r5, r0 cmp r1, #0 beq.n <_free_r+0x8c> ldr.w r3, [r1, #-4] subs r4, r1, #4 cmp r3, #0 it lt addlt r4, r4, r3 bl <__malloc_lock> ldr r2, [pc, #116] @ (<_free_r+0x90>) ldr r3, [r2, #0] cbnz r3, <_free_r+0x2c> str r3, [r4, #4] str r4, [r2, #0] mov r0, r5 ldmia.w sp!, {r3, r4, r5, lr} b.w <__malloc_unlock> cmp r3, r4 bls.n <_free_r+0x42> ldr r0, [r4, #0] adds r1, r4, r0 cmp r3, r1 itttt eq ldreq r1, [r3, #0] ldreq r3, [r3, #4] addeq r1, r1, r0 streq r1, [r4, #0] b.n <_free_r+0x1e> mov r2, r3 ldr r3, [r3, #4] cbz r3, <_free_r+0x4c> cmp r3, r4 bls.n <_free_r+0x42> ldr r1, [r2, #0] adds r0, r2, r1 cmp r0, r4 bne.n <_free_r+0x6c> ldr r0, [r4, #0] add r1, r0 adds r0, r2, r1 cmp r3, r0 str r1, [r2, #0] bne.n <_free_r+0x22> ldr r0, [r3, #0] ldr r3, [r3, #4] str r3, [r2, #4] add r0, r1 str r0, [r2, #0] b.n <_free_r+0x22> bls.n <_free_r+0x74> movs r3, #12 str r3, [r5, #0] b.n <_free_r+0x22> ldr r0, [r4, #0] adds r1, r4, r0 cmp r3, r1 itt eq ldreq r1, [r3, #0] ldreq r3, [r3, #4] str r3, [r4, #4] itt eq addeq r1, r1, r0 streq r1, [r4, #0] str r4, [r2, #4] b.n <_free_r+0x22> pop {r3, r4, r5, pc} nop .word 0x20001f04 <__sfputc_r>: ldr r3, [r2, #8] subs r3, #1 cmp r3, #0 push {r4} str r3, [r2, #8] bge.n <__sfputc_r+0x1c> ldr r4, [r2, #24] cmp r3, r4 blt.n <__sfputc_r+0x16> cmp r1, #10 bne.n <__sfputc_r+0x1c> pop {r4} b.w <__swbuf_r> ldr r3, [r2, #0] adds r0, r3, #1 str r0, [r2, #0] strb r1, [r3, #0] mov r0, r1 pop {r4} bx lr <__sfputs_r>: push {r3, r4, r5, r6, r7, lr} mov r6, r0 mov r7, r1 mov r4, r2 adds r5, r2, r3 cmp r4, r5 bne.n <__sfputs_r+0x12> movs r0, #0 b.n <__sfputs_r+0x22> ldrb.w r1, [r4], #1 mov r2, r7 mov r0, r6 bl <__sfputc_r> adds r3, r0, #1 bne.n <__sfputs_r+0xa> pop {r3, r4, r5, r6, r7, pc} ... <_vfiprintf_r>: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} mov r5, r1 sub sp, #88 @ 0x58 mov r4, r2 mov r7, r3 mov r6, r0 cbz r0, <_vfiprintf_r+0x18> ldr r3, [r0, #32] cbnz r3, <_vfiprintf_r+0x18> bl <__sinit> ldrh r3, [r5, #12] lsls r3, r3, #28 bpl.n <_vfiprintf_r+0xd2> ldr r3, [r5, #16] cmp r3, #0 beq.n <_vfiprintf_r+0xd2> movs r3, #0 str r3, [sp, #36] @ 0x24 movs r3, #32 strb.w r3, [sp, #41] @ 0x29 str r7, [sp, #12] movs r3, #48 @ 0x30 ldr r7, [pc, #388] @ (<_vfiprintf_r+0x1b8>) strb.w r3, [sp, #42] @ 0x2a mov.w r8, #1 mov r3, r4 mov r9, r3 ldrb.w r2, [r3], #1 cbz r2, <_vfiprintf_r+0x4a> cmp r2, #37 @ 0x25 bne.n <_vfiprintf_r+0x3e> subs.w sl, r9, r4 beq.n <_vfiprintf_r+0x68> mov r3, sl mov r2, r4 mov r1, r5 mov r0, r6 bl <__sfputs_r> adds r0, #1 beq.w <_vfiprintf_r+0x1ac> ldr r2, [sp, #36] @ 0x24 add r2, sl str r2, [sp, #36] @ 0x24 ldrb.w r3, [r9] cmp r3, #0 beq.w <_vfiprintf_r+0x1ac> movs r3, #0 mov.w r2, #4294967295 @ 0xffffffff strd r2, r3, [sp, #20] add.w r9, r9, #1 str r3, [sp, #16] str r3, [sp, #28] strb.w r3, [sp, #83] @ 0x53 mov r4, r9 movs r2, #5 ldrb.w r1, [r4], #1 ldr r0, [pc, #292] @ (<_vfiprintf_r+0x1b8>) bl ldr r2, [sp, #16] cbnz r0, <_vfiprintf_r+0xe8> lsls r0, r2, #27 itt mi movmi r3, #32 strbmi.w r3, [sp, #83] @ 0x53 lsls r1, r2, #28 itt mi movmi r3, #43 @ 0x2b strbmi.w r3, [sp, #83] @ 0x53 ldrb.w r3, [r9] cmp r3, #42 @ 0x2a beq.n <_vfiprintf_r+0xf6> ldr r2, [sp, #28] mov r4, r9 movs r0, #0 mov.w ip, #10 mov r1, r4 ldrb.w r3, [r1], #1 subs r3, #48 @ 0x30 cmp r3, #9 bls.n <_vfiprintf_r+0x178> cbz r0, <_vfiprintf_r+0x110> str r2, [sp, #28] b.n <_vfiprintf_r+0x110> mov r1, r5 mov r0, r6 bl <__swsetup_r> cmp r0, #0 beq.n <_vfiprintf_r+0x24> mov.w r0, #4294967295 @ 0xffffffff add sp, #88 @ 0x58 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} subs r3, r0, r7 lsl.w r3, r8, r3 orrs r3, r2 str r3, [sp, #16] mov r9, r4 b.n <_vfiprintf_r+0x88> ldr r3, [sp, #12] adds r1, r3, #4 ldr r3, [r3, #0] str r1, [sp, #12] cmp r3, #0 ittet lt neglt r3, r3 orrlt.w r2, r2, #2 strge r3, [sp, #28] strlt r3, [sp, #28] it lt strlt r2, [sp, #16] ldrb r3, [r4, #0] cmp r3, #46 @ 0x2e bne.n <_vfiprintf_r+0x12c> ldrb r3, [r4, #1] cmp r3, #42 @ 0x2a bne.n <_vfiprintf_r+0x182> ldr r3, [sp, #12] adds r2, r3, #4 ldr r3, [r3, #0] str r2, [sp, #12] orr.w r3, r3, r3, asr #31 adds r4, #2 str r3, [sp, #20] ldr.w r9, [pc, #140] @ <_vfiprintf_r+0x1bc> ldrb r1, [r4, #0] movs r2, #3 mov r0, r9 bl cbz r0, <_vfiprintf_r+0x14c> ldr r3, [sp, #16] sub.w r0, r0, r9 movs r2, #64 @ 0x40 lsls r2, r0 orrs r3, r2 adds r4, #1 str r3, [sp, #16] ldrb.w r1, [r4], #1 ldr r0, [pc, #108] @ (<_vfiprintf_r+0x1c0>) strb.w r1, [sp, #40] @ 0x28 movs r2, #6 bl add r3, sp, #12 str r3, [sp, #0] mov r2, r5 ldr r3, [pc, #96] @ (<_vfiprintf_r+0x1c4>) add r1, sp, #16 mov r0, r6 bl <_printf_i> adds r2, r0, #1 beq.n <_vfiprintf_r+0x1ac> ldr r3, [sp, #36] @ 0x24 add r3, r0 str r3, [sp, #36] @ 0x24 b.n <_vfiprintf_r+0x3c> mla r2, ip, r2, r3 mov r4, r1 movs r0, #1 b.n <_vfiprintf_r+0xc0> movs r3, #0 adds r4, #1 str r3, [sp, #20] mov r1, r3 mov.w ip, #10 mov r0, r4 ldrb.w r2, [r0], #1 subs r2, #48 @ 0x30 cmp r2, #9 bls.n <_vfiprintf_r+0x1a2> cmp r3, #0 beq.n <_vfiprintf_r+0x12c> str r1, [sp, #20] b.n <_vfiprintf_r+0x12c> mla r1, ip, r1, r2 mov r4, r0 movs r3, #1 b.n <_vfiprintf_r+0x18e> ldrh r3, [r5, #12] lsls r3, r3, #25 bmi.n <_vfiprintf_r+0xde> ldr r0, [sp, #36] @ 0x24 b.n <_vfiprintf_r+0xe2> nop .word 0x60008f4e .word 0x60008f54 .word 0x60008f58 .word 0x6000802b <_printf_common>: stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, lr} mov r6, r2 mov r8, r3 ldr r2, [r1, #8] ldr r3, [r1, #16] ldr.w r9, [sp, #32] cmp r3, r2 it lt movlt r3, r2 str r3, [r6, #0] ldrb.w r2, [r1, #67] @ 0x43 mov r7, r0 mov r4, r1 cbz r2, <_printf_common+0x26> adds r3, #1 str r3, [r6, #0] ldr r3, [r4, #0] lsls r1, r3, #26 ittt mi ldrmi r3, [r6, #0] addmi r3, #2 strmi r3, [r6, #0] ldr r5, [r4, #0] ands.w r5, r5, #6 bne.n <_printf_common+0x48> add.w sl, r4, #25 ldr r3, [r4, #12] ldr r2, [r6, #0] subs r3, r3, r2 cmp r3, r5 bgt.n <_printf_common+0x96> ldrb.w r3, [r4, #67] @ 0x43 ldr r2, [r4, #0] subs r3, #0 it ne movne r3, #1 lsls r2, r2, #26 bmi.n <_printf_common+0xb0> add.w r2, r4, #67 @ 0x43 mov r1, r8 mov r0, r7 blx r9 adds r0, #1 beq.n <_printf_common+0xa4> ldr r3, [r4, #0] ldr r2, [r4, #16] and.w r3, r3, #6 cmp r3, #4 ittt eq ldreq r5, [r4, #12] ldreq r3, [r6, #0] subeq r5, r5, r3 ldr r3, [r4, #8] ite eq biceq.w r5, r5, r5, asr #31 movne r5, #0 cmp r3, r2 itt gt subgt r3, r3, r2 addgt r5, r5, r3 movs r6, #0 adds r4, #26 cmp r5, r6 bne.n <_printf_common+0xc8> movs r0, #0 b.n <_printf_common+0xa8> movs r3, #1 mov r2, sl mov r1, r8 mov r0, r7 blx r9 adds r0, #1 bne.n <_printf_common+0xac> mov.w r0, #4294967295 @ 0xffffffff ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} adds r5, #1 b.n <_printf_common+0x3e> adds r1, r4, r3 adds r2, r3, #1 movs r0, #48 @ 0x30 strb.w r0, [r1, #67] @ 0x43 add r2, r4 ldrb.w r1, [r4, #69] @ 0x45 strb.w r1, [r2, #67] @ 0x43 adds r3, #2 b.n <_printf_common+0x58> movs r3, #1 mov r2, r4 mov r1, r8 mov r0, r7 blx r9 adds r0, #1 beq.n <_printf_common+0xa4> adds r6, #1 b.n <_printf_common+0x8e> ... <_printf_i>: stmdb sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, lr} ldrb r7, [r1, #24] ldr r6, [sp, #48] @ 0x30 cmp r7, #120 @ 0x78 mov r9, r2 mov r8, r0 mov r4, r1 mov sl, r3 add.w r2, r1, #67 @ 0x43 bhi.n <_printf_i+0x28> cmp r7, #98 @ 0x62 bhi.n <_printf_i+0x32> cmp r7, #0 beq.w <_printf_i+0x1c4> cmp r7, #88 @ 0x58 beq.w <_printf_i+0x198> add.w r6, r4, #66 @ 0x42 strb.w r7, [r4, #66] @ 0x42 b.n <_printf_i+0xa8> sub.w r3, r7, #99 @ 0x63 cmp r3, #21 bhi.n <_printf_i+0x28> add r1, pc, #4 @ (adr r1, <_printf_i+0x40>) ldr.w pc, [r1, r3, lsl #2] .word 0x6000838d .word 0x600083a1 .word 0x6000831d .word 0x6000831d .word 0x6000831d .word 0x6000831d .word 0x600083a1 .word 0x6000831d .word 0x6000831d .word 0x6000831d .word 0x6000831d .word 0x6000849f .word 0x600083cb .word 0x60008459 .word 0x6000831d .word 0x6000831d .word 0x600084c1 .word 0x6000831d .word 0x600083cb .word 0x6000831d .word 0x6000831d .word 0x60008461 ldr r3, [r6, #0] adds r2, r3, #4 ldr r3, [r3, #0] str r2, [r6, #0] add.w r6, r4, #66 @ 0x42 strb.w r3, [r4, #66] @ 0x42 movs r3, #1 b.n <_printf_i+0x1e6> ldr r3, [r6, #0] ldr r0, [r4, #0] adds r1, r3, #4 str r1, [r6, #0] lsls r6, r0, #24 bpl.n <_printf_i+0xbc> ldr r5, [r3, #0] b.n <_printf_i+0xc4> lsls r5, r0, #25 bpl.n <_printf_i+0xb8> ldrsh.w r5, [r3] cmp r5, #0 bge.n <_printf_i+0xd0> movs r3, #45 @ 0x2d negs r5, r5 strb.w r3, [r4, #67] @ 0x43 ldr r0, [pc, #352] @ (<_printf_i+0x234>) movs r3, #10 b.n <_printf_i+0xfa> ldr r1, [r4, #0] ldr r3, [r6, #0] lsls r0, r1, #24 ldr.w r5, [r3], #4 bmi.n <_printf_i+0xe8> lsls r1, r1, #25 it mi uxthmi r5, r5 cmp r7, #111 @ 0x6f ldr r0, [pc, #328] @ (<_printf_i+0x234>) str r3, [r6, #0] ite ne movne r3, #10 moveq r3, #8 movs r1, #0 strb.w r1, [r4, #67] @ 0x43 ldr r6, [r4, #4] str r6, [r4, #8] cmp r6, #0 blt.n <_printf_i+0x10e> ldr r1, [r4, #0] orrs r6, r5 bic.w r1, r1, #4 str r1, [r4, #0] beq.n <_printf_i+0x1a6> mov r6, r2 udiv r1, r5, r3 mls r7, r3, r1, r5 ldrb r7, [r0, r7] strb.w r7, [r6, #-1]! mov r7, r5 cmp r3, r7 mov r5, r1 bls.n <_printf_i+0x110> cmp r3, #8 bne.n <_printf_i+0x142> ldr r3, [r4, #0] lsls r7, r3, #31 bpl.n <_printf_i+0x142> ldr r3, [r4, #16] ldr r1, [r4, #4] cmp r1, r3 ittt le movle r3, #48 @ 0x30 strble.w r3, [r6, #-1] addle.w r6, r6, #4294967295 @ 0xffffffff subs r2, r2, r6 str r2, [r4, #16] str.w sl, [sp] mov r3, r9 add r2, sp, #12 mov r1, r4 mov r0, r8 bl <_printf_common> adds r0, #1 bne.n <_printf_i+0x1f0> mov.w r0, #4294967295 @ 0xffffffff add sp, #16 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, sl, pc} ldr r3, [r4, #0] orr.w r3, r3, #32 str r3, [r4, #0] ldr r0, [pc, #200] @ (<_printf_i+0x238>) movs r7, #120 @ 0x78 strb.w r7, [r4, #69] @ 0x45 ldr r3, [r4, #0] ldr r1, [r6, #0] lsls r7, r3, #24 ldr.w r5, [r1], #4 bmi.n <_printf_i+0x186> lsls r7, r3, #25 it mi uxthmi r5, r5 str r1, [r6, #0] lsls r1, r3, #31 itt mi orrmi.w r3, r3, #32 strmi r3, [r4, #0] cbz r5, <_printf_i+0x19c> movs r3, #16 b.n <_printf_i+0xf4> ldr r0, [pc, #152] @ (<_printf_i+0x234>) b.n <_printf_i+0x170> ldr r3, [r4, #0] bic.w r3, r3, #32 str r3, [r4, #0] b.n <_printf_i+0x194> mov r6, r2 b.n <_printf_i+0x126> ldr r3, [r6, #0] ldr r5, [r4, #0] ldr r1, [r4, #20] adds r0, r3, #4 str r0, [r6, #0] lsls r6, r5, #24 ldr r3, [r3, #0] bpl.n <_printf_i+0x1be> str r1, [r3, #0] b.n <_printf_i+0x1c4> lsls r0, r5, #25 bpl.n <_printf_i+0x1ba> strh r1, [r3, #0] movs r3, #0 str r3, [r4, #16] mov r6, r2 b.n <_printf_i+0x146> ldr r3, [r6, #0] adds r2, r3, #4 str r2, [r6, #0] ldr r6, [r3, #0] ldr r2, [r4, #4] movs r1, #0 mov r0, r6 bl cbz r0, <_printf_i+0x1e4> subs r0, r0, r6 str r0, [r4, #4] ldr r3, [r4, #4] str r3, [r4, #16] movs r3, #0 strb.w r3, [r4, #67] @ 0x43 b.n <_printf_i+0x146> ldr r3, [r4, #16] mov r2, r6 mov r1, r9 mov r0, r8 blx sl adds r0, #1 beq.n <_printf_i+0x15a> ldr r3, [r4, #0] lsls r3, r3, #30 bmi.n <_printf_i+0x22c> ldr r0, [r4, #12] ldr r3, [sp, #12] cmp r0, r3 it lt movlt r0, r3 b.n <_printf_i+0x15e> movs r3, #1 mov r2, r6 mov r1, r9 mov r0, r8 blx sl adds r0, #1 beq.n <_printf_i+0x15a> adds r5, #1 ldr r3, [r4, #12] ldr r1, [sp, #12] subs r3, r3, r1 cmp r3, r5 bgt.n <_printf_i+0x210> b.n <_printf_i+0x204> movs r5, #0 add.w r6, r4, #25 b.n <_printf_i+0x220> .word 0x60008f5f .word 0x60008f70 : movs r3, #0 push {r4, lr} mov r4, r0 strd r3, r3, [r0] strd r3, r3, [r0, #16] str r3, [r0, #8] strh r1, [r0, #12] str r3, [r0, #100] @ 0x64 strh r2, [r0, #14] str r3, [r0, #24] mov r1, r3 movs r2, #8 adds r0, #92 @ 0x5c bl ldr r3, [pc, #20] @ () str r3, [r4, #36] @ 0x24 ldr r3, [pc, #20] @ () str r3, [r4, #40] @ 0x28 ldr r3, [pc, #20] @ () str r3, [r4, #44] @ 0x2c ldr r3, [pc, #20] @ () str r4, [r4, #32] str r3, [r4, #48] @ 0x30 pop {r4, pc} nop .word 0x60008665 .word 0x60008687 .word 0x600086bf .word 0x600086e3 : ldr r2, [pc, #8] @ () ldr r1, [pc, #12] @ () ldr r0, [pc, #12] @ () b.w <_fwalk_sglue> nop .word 0x20000d28 .word 0x60008915 .word 0x20000cdc : ldr r1, [r0, #4] ldr r3, [pc, #48] @ () cmp r1, r3 push {r4, lr} mov r4, r0 beq.n bl <_fflush_r> ldr r1, [r4, #8] ldr r3, [pc, #36] @ () cmp r1, r3 beq.n mov r0, r4 bl <_fflush_r> ldr r1, [r4, #12] ldr r3, [pc, #24] @ () cmp r1, r3 beq.n mov r0, r4 ldmia.w sp!, {r4, lr} b.w <_fflush_r> pop {r4, pc} nop .word 0x20001f08 .word 0x20001f70 .word 0x20001fd8 : push {r4, lr} ldr r3, [pc, #44] @ () ldr r4, [pc, #44] @ () ldr r2, [pc, #48] @ () str r2, [r3, #0] mov r0, r4 movs r2, #0 movs r1, #4 bl add.w r0, r4, #104 @ 0x68 movs r2, #1 movs r1, #9 bl add.w r0, r4, #208 @ 0xd0 movs r2, #2 ldmia.w sp!, {r4, lr} movs r1, #18 b.w .word 0x20002040 .word 0x20001f08 .word 0x60008579 <__sinit>: ldr r3, [r0, #32] cbnz r3, <__sinit+0x12> ldr r3, [pc, #12] @ (<__sinit+0x14>) str r3, [r0, #32] ldr r3, [pc, #12] @ (<__sinit+0x18>) ldr r3, [r3, #0] cbnz r3, <__sinit+0x12> b.w bx lr .word 0x60008591 .word 0x20002040 <_fwalk_sglue>: stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, lr} mov r7, r0 mov r8, r1 mov r4, r2 movs r6, #0 ldrd r9, r5, [r4, #4] subs.w r9, r9, #1 bpl.n <_fwalk_sglue+0x22> ldr r4, [r4, #0] cmp r4, #0 bne.n <_fwalk_sglue+0xc> mov r0, r6 ldmia.w sp!, {r3, r4, r5, r6, r7, r8, r9, pc} ldrh r3, [r5, #12] cmp r3, #1 bls.n <_fwalk_sglue+0x38> ldrsh.w r3, [r5, #14] adds r3, #1 beq.n <_fwalk_sglue+0x38> mov r1, r5 mov r0, r7 blx r8 orrs r6, r0 adds r5, #104 @ 0x68 b.n <_fwalk_sglue+0x10> <__sread>: push {r4, lr} mov r4, r1 ldrsh.w r1, [r1, #14] bl <_read_r> cmp r0, #0 itete ge ldrge r3, [r4, #84] @ 0x54 ldrhlt r3, [r4, #12] addge r3, r3, r0 biclt.w r3, r3, #4096 @ 0x1000 ite ge strge r3, [r4, #84] @ 0x54 strhlt r3, [r4, #12] pop {r4, pc} <__swrite>: stmdb sp!, {r4, r5, r6, r7, r8, lr} mov r7, r3 ldrh r3, [r1, #12] lsls r3, r3, #23 mov r5, r0 mov r4, r1 mov r6, r2 bpl.n <__swrite+0x1e> ldrsh.w r1, [r1, #14] movs r3, #2 movs r2, #0 bl <_lseek_r> ldrh r3, [r4, #12] ldrsh.w r1, [r4, #14] bic.w r3, r3, #4096 @ 0x1000 strh r3, [r4, #12] mov r2, r6 mov r3, r7 mov r0, r5 ldmia.w sp!, {r4, r5, r6, r7, r8, lr} b.w <_write_r> <__sseek>: push {r4, lr} mov r4, r1 ldrsh.w r1, [r1, #14] bl <_lseek_r> adds r3, r0, #1 ldrh r3, [r4, #12] itete ne strne r0, [r4, #84] @ 0x54 biceq.w r3, r3, #4096 @ 0x1000 orrne.w r3, r3, #4096 @ 0x1000 strheq r3, [r4, #12] it ne strhne r3, [r4, #12] pop {r4, pc} <__sclose>: ldrsh.w r1, [r1, #14] b.w <_close_r> <__swbuf_r>: push {r3, r4, r5, r6, r7, lr} mov r6, r1 mov r4, r2 mov r5, r0 cbz r0, <__swbuf_r+0x12> ldr r3, [r0, #32] cbnz r3, <__swbuf_r+0x12> bl <__sinit> ldr r3, [r4, #24] str r3, [r4, #8] ldrh r3, [r4, #12] lsls r2, r3, #28 bpl.n <__swbuf_r+0x20> ldr r3, [r4, #16] cbnz r3, <__swbuf_r+0x32> mov r1, r4 mov r0, r5 bl <__swsetup_r> cbz r0, <__swbuf_r+0x32> mov.w r7, #4294967295 @ 0xffffffff mov r0, r7 pop {r3, r4, r5, r6, r7, pc} ldr r3, [r4, #0] ldr r2, [r4, #16] subs r0, r3, r2 ldr r3, [r4, #20] uxtb r6, r6 cmp r3, r0 mov r7, r6 bgt.n <__swbuf_r+0x4e> mov r1, r4 mov r0, r5 bl <_fflush_r> cmp r0, #0 bne.n <__swbuf_r+0x2a> ldr r3, [r4, #8] subs r3, #1 str r3, [r4, #8] ldr r3, [r4, #0] adds r2, r3, #1 str r2, [r4, #0] strb r6, [r3, #0] ldr r2, [r4, #20] adds r3, r0, #1 cmp r2, r3 beq.n <__swbuf_r+0x6e> ldrh r3, [r4, #12] lsls r3, r3, #31 bpl.n <__swbuf_r+0x2e> cmp r6, #10 bne.n <__swbuf_r+0x2e> mov r1, r4 mov r0, r5 bl <_fflush_r> cmp r0, #0 beq.n <__swbuf_r+0x2e> b.n <__swbuf_r+0x2a> ... <__swsetup_r>: push {r3, r4, r5, lr} ldr r3, [pc, #164] @ (<__swsetup_r+0xa8>) mov r5, r0 ldr r0, [r3, #0] mov r4, r1 cbz r0, <__swsetup_r+0x14> ldr r3, [r0, #32] cbnz r3, <__swsetup_r+0x14> bl <__sinit> ldrsh.w r3, [r4, #12] lsls r1, r3, #28 bmi.n <__swsetup_r+0x62> lsls r2, r3, #27 bmi.n <__swsetup_r+0x30> movs r2, #9 str r2, [r5, #0] orr.w r3, r3, #64 @ 0x40 strh r3, [r4, #12] mov.w r0, #4294967295 @ 0xffffffff b.n <__swsetup_r+0x98> lsls r0, r3, #29 bpl.n <__swsetup_r+0x5a> ldr r1, [r4, #52] @ 0x34 cbz r1, <__swsetup_r+0x4a> add.w r3, r4, #68 @ 0x44 cmp r1, r3 beq.n <__swsetup_r+0x46> mov r0, r5 bl <_free_r> movs r3, #0 str r3, [r4, #52] @ 0x34 ldrh r3, [r4, #12] bic.w r3, r3, #36 @ 0x24 strh r3, [r4, #12] movs r3, #0 str r3, [r4, #4] ldr r3, [r4, #16] str r3, [r4, #0] ldrh r3, [r4, #12] orr.w r3, r3, #8 strh r3, [r4, #12] ldr r3, [r4, #16] cbnz r3, <__swsetup_r+0x7a> ldrh r3, [r4, #12] and.w r3, r3, #640 @ 0x280 cmp.w r3, #512 @ 0x200 beq.n <__swsetup_r+0x7a> mov r1, r4 mov r0, r5 bl <__smakebuf_r> ldrsh.w r3, [r4, #12] ands.w r2, r3, #1 beq.n <__swsetup_r+0x9a> movs r2, #0 str r2, [r4, #8] ldr r2, [r4, #20] negs r2, r2 str r2, [r4, #24] ldr r2, [r4, #16] cbnz r2, <__swsetup_r+0xa4> ands.w r0, r3, #128 @ 0x80 bne.n <__swsetup_r+0x24> pop {r3, r4, r5, pc} lsls r1, r3, #30 it pl ldrpl r2, [r4, #20] str r2, [r4, #8] b.n <__swsetup_r+0x8e> movs r0, #0 b.n <__swsetup_r+0x98> .word 0x20000cd8 <__sflush_r>: ldrsh.w r2, [r1, #12] push {r3, r4, r5, r6, r7, lr} lsls r6, r2, #28 mov r5, r0 mov r4, r1 bmi.n <__sflush_r+0xb8> ldr r3, [r1, #4] cmp r3, #0 bgt.n <__sflush_r+0x1a> ldr r3, [r1, #64] @ 0x40 cmp r3, #0 ble.n <__sflush_r+0xac> ldr r6, [r4, #44] @ 0x2c cmp r6, #0 beq.n <__sflush_r+0xac> movs r3, #0 ands.w r2, r2, #4096 @ 0x1000 ldr r7, [r5, #0] ldr r1, [r4, #32] str r3, [r5, #0] beq.n <__sflush_r+0x90> ldr r2, [r4, #84] @ 0x54 ldrh r3, [r4, #12] lsls r1, r3, #29 bpl.n <__sflush_r+0x42> ldr r3, [r4, #4] subs r2, r2, r3 ldr r3, [r4, #52] @ 0x34 cbz r3, <__sflush_r+0x42> ldr r3, [r4, #64] @ 0x40 subs r2, r2, r3 movs r3, #0 ldr r6, [r4, #44] @ 0x2c ldr r1, [r4, #32] mov r0, r5 blx r6 adds r3, r0, #1 ldrh r3, [r4, #12] bne.n <__sflush_r+0x60> ldr r1, [r5, #0] cmp r1, #29 bhi.n <__sflush_r+0xb0> ldr r2, [pc, #160] @ (<__sflush_r+0xfc>) lsrs r2, r1 lsls r6, r2, #31 bpl.n <__sflush_r+0xb0> movs r2, #0 str r2, [r4, #4] lsls r1, r3, #19 ldr r2, [r4, #16] str r2, [r4, #0] bpl.n <__sflush_r+0x76> adds r2, r0, #1 bne.n <__sflush_r+0x74> ldr r3, [r5, #0] cbnz r3, <__sflush_r+0x76> str r0, [r4, #84] @ 0x54 ldr r1, [r4, #52] @ 0x34 str r7, [r5, #0] cbz r1, <__sflush_r+0xac> add.w r3, r4, #68 @ 0x44 cmp r1, r3 beq.n <__sflush_r+0x8a> mov r0, r5 bl <_free_r> movs r3, #0 str r3, [r4, #52] @ 0x34 b.n <__sflush_r+0xac> movs r3, #1 mov r0, r5 blx r6 mov r2, r0 adds r0, r2, #1 bne.n <__sflush_r+0x30> ldr r3, [r5, #0] cmp r3, #0 beq.n <__sflush_r+0x30> cmp r3, #29 beq.n <__sflush_r+0xaa> cmp r3, #22 bne.n <__sflush_r+0xe6> str r7, [r5, #0] movs r0, #0 b.n <__sflush_r+0xf4> orr.w r3, r3, #64 @ 0x40 sxth r3, r3 b.n <__sflush_r+0xee> ldr r7, [r1, #16] cmp r7, #0 beq.n <__sflush_r+0xac> lsls r3, r2, #30 ldr r6, [r1, #0] it eq ldreq r3, [r1, #20] str r7, [r1, #0] it ne movne r3, #0 subs r6, r6, r7 str r3, [r1, #8] cmp r6, #0 ble.n <__sflush_r+0xac> ldr r1, [r4, #32] ldr.w ip, [r4, #40] @ 0x28 mov r3, r6 mov r2, r7 mov r0, r5 blx ip cmp r0, #0 bgt.n <__sflush_r+0xf6> ldrsh.w r3, [r4, #12] orr.w r3, r3, #64 @ 0x40 strh r3, [r4, #12] mov.w r0, #4294967295 @ 0xffffffff pop {r3, r4, r5, r6, r7, pc} add r7, r0 subs r6, r6, r0 b.n <__sflush_r+0xd0> .word 0x20400001 <_fflush_r>: push {r3, r4, r5, lr} ldr r3, [r1, #16] mov r4, r0 mov r5, r1 cbz r3, <_fflush_r+0x26> cbz r0, <_fflush_r+0x14> ldr r3, [r0, #32] cbnz r3, <_fflush_r+0x14> bl <__sinit> ldrsh.w r3, [r5, #12] cbz r3, <_fflush_r+0x26> mov r1, r5 mov r0, r4 ldmia.w sp!, {r3, r4, r5, lr} b.w <__sflush_r> movs r0, #0 pop {r3, r4, r5, pc} <__swhatbuf_r>: push {r4, r5, r6, lr} mov r4, r1 ldrsh.w r1, [r1, #14] cmp r1, #0 sub sp, #88 @ 0x58 mov r5, r2 mov r6, r3 bge.n <__swhatbuf_r+0x2e> ldrh r3, [r4, #12] tst.w r3, #128 @ 0x80 mov.w r1, #0 ite ne movne r3, #64 @ 0x40 moveq.w r3, #1024 @ 0x400 movs r0, #0 str r1, [r6, #0] str r3, [r5, #0] add sp, #88 @ 0x58 pop {r4, r5, r6, pc} mov r2, sp bl <_fstat_r> cmp r0, #0 blt.n <__swhatbuf_r+0x12> ldr r1, [sp, #4] and.w r1, r1, #61440 @ 0xf000 sub.w r3, r1, #8192 @ 0x2000 negs r1, r3 adcs r1, r3 mov.w r3, #1024 @ 0x400 b.n <__swhatbuf_r+0x24> <__smakebuf_r>: ldrh r3, [r1, #12] push {r0, r1, r2, r4, r5, r6, r7, lr} lsls r5, r3, #30 mov r6, r0 mov r4, r1 bpl.n <__smakebuf_r+0x1c> add.w r3, r4, #71 @ 0x47 str r3, [r4, #0] str r3, [r4, #16] movs r3, #1 str r3, [r4, #20] add sp, #12 pop {r4, r5, r6, r7, pc} add r3, sp, #4 mov r2, sp bl <__swhatbuf_r> ldr r7, [sp, #0] mov r5, r0 mov r1, r7 mov r0, r6 bl <_malloc_r> cbnz r0, <__smakebuf_r+0x46> ldrsh.w r3, [r4, #12] lsls r2, r3, #22 bmi.n <__smakebuf_r+0x18> bic.w r3, r3, #3 orr.w r3, r3, #2 strh r3, [r4, #12] b.n <__smakebuf_r+0xc> ldrh r3, [r4, #12] str r0, [r4, #0] orr.w r3, r3, #128 @ 0x80 strh r3, [r4, #12] ldr r3, [sp, #4] strd r0, r7, [r4, #16] cbz r3, <__smakebuf_r+0x70> ldrsh.w r1, [r4, #14] mov r0, r6 bl <_isatty_r> cbz r0, <__smakebuf_r+0x70> ldrh r3, [r4, #12] bic.w r3, r3, #3 orr.w r3, r3, #1 strh r3, [r4, #12] ldrh r3, [r4, #12] orrs r5, r3 strh r5, [r4, #12] b.n <__smakebuf_r+0x18>