Skip to content

Commit db1c0dd

Browse files
committed
Add a soft_reset function that jumps to bootloader
With the CW-KBD all boxed up, it is impossible to press the reset button for a firmware upgrade. This makes it possible that, as long as we are running a working firmware, we can jump to the bootloader without taking the box apart. Signed-off-by: Vernon Mauery <[email protected]>
1 parent 186db7a commit db1c0dd

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

Makefile

+8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ BOARD =
6363
# software delays.
6464
F_CPU = 16000000
6565

66+
# Boot start address
67+
# We need to know the boot start address so we can jump to it on a soft
68+
# reset. This is so we don't have to physically press the reset button
69+
# in order to run the bootloader to flash new firmware.
70+
BOOT_START = 0x7c00
6671

6772
# Input clock frequency.
6873
# This will define a symbol, F_CLOCK, in all source code files equal to the
@@ -181,19 +186,22 @@ CDEFS = -DF_CPU=$(F_CPU)UL
181186
CDEFS += -DF_CLOCK=$(F_CLOCK)UL
182187
CDEFS += -DBOARD=BOARD_$(BOARD)
183188
CDEFS += $(LUFA_OPTS)
189+
CDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
184190

185191

186192
# Place -D or -U options here for ASM sources
187193
ADEFS = -DF_CPU=$(F_CPU)
188194
ADEFS += -DF_CLOCK=$(F_CLOCK)UL
189195
ADEFS += -DBOARD=BOARD_$(BOARD)
190196
ADEFS += $(LUFA_OPTS)
197+
ADEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
191198

192199
# Place -D or -U options here for C++ sources
193200
CPPDEFS = -DF_CPU=$(F_CPU)UL
194201
CPPDEFS += -DF_CLOCK=$(F_CLOCK)UL
195202
CPPDEFS += -DBOARD=BOARD_$(BOARD)
196203
CPPDEFS += $(LUFA_OPTS)
204+
CPPDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
197205
#CPPDEFS += -D__STDC_LIMIT_MACROS
198206
#CPPDEFS += -D__STDC_CONSTANT_MACROS
199207

cw-kbd.c

+28-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
static void hid_nq(uint8_t c);
3737
void set_command_mode(bool mode);
3838
static void exit_command_mode(void);
39+
void soft_reset(void);
3940

4041
uint8_t hid_in_report_buffer[sizeof(USB_KeyboardReport_Data_t)];
4142

@@ -447,6 +448,10 @@ static void inject_string(void) {
447448
}
448449
}
449450

451+
static void clear_led(void) {
452+
PORTD &= ~_BV(PD6);
453+
}
454+
450455
static void set_led(void) {
451456
PORTD |= _BV(PD6);
452457
}
@@ -556,6 +561,9 @@ void command_mode_cb(uint8_t v) {
556561
cw_char(':');
557562
cw_char(v);
558563
break;
564+
case 'o': /* jump to reset */
565+
soft_reset();
566+
break;
559567
case 'q': /* quiet mode */
560568
cw_set_beeper(!settings_get_beeper());
561569
cm_state = command_output;
@@ -874,6 +882,10 @@ void int6_enable(void) {
874882
EIMSK |= _BV(INT6);
875883
}
876884

885+
static void int6_disable(void) {
886+
EIMSK &= ~_BV(INT6);
887+
}
888+
877889
bool command_mode = false;
878890
void set_command_mode(bool mode) {
879891
command_mode = mode;
@@ -932,11 +944,26 @@ void int6_debounce(void) {
932944

933945
/* command mode button */
934946
ISR(INT6_vect) {
935-
EIMSK &= ~_BV(INT6);
947+
int6_disable();
936948
debug("INT6\n");
937949
ms_tick_register(int6_debounce, TICK_INT6_DEBOUNCE, 1);
938950
}
939951

952+
__attribute__((naked)) void soft_reset(void) {
953+
uint8_t mcucr;
954+
USB_ShutDown();
955+
while (USB_IsInitialized);
956+
cli();
957+
mcucr = MCUCR | _BV(IVCE) | _BV(IVSEL);
958+
MCUCR |= _BV(IVCE);
959+
MCUCR = mcucr;
960+
cw_fini();
961+
int6_disable();
962+
clear_led();
963+
ms_tick_stop();
964+
asm volatile ("jmp %0" : : "i"(BOOT_START_ADDR));
965+
}
966+
940967
void sw_init(void) {
941968
settings_init();
942969
ms_tick_init();

cw.c

+6
Original file line numberDiff line numberDiff line change
@@ -1053,3 +1053,9 @@ void cw_init(uint8_t wpm, cw_dq_cb_t cb) {
10531053
EIMSK |= (_BV(INT1) | _BV(INT0));
10541054
}
10551055

1056+
void cw_fini(void) {
1057+
EIMSK &= ~(_BV(INT1) | _BV(INT0));
1058+
cw_set_dq_callback(NULL);
1059+
cw_clear_queues();
1060+
timer3_stop();
1061+
}

cw.h

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ didah_queue_t cw_get_left_key(void);
8585
void cw_init(uint8_t wpm, cw_dq_cb_t cb);
8686
void cw_set_word_space(bool spaces);
8787
void cw_set_frequency(uint16_t hz);
88+
void cw_fini(void);
8889
void cw_set_keying_mode(keying_mode_t mode);
8990
void cw_set_dq_callback(cw_dq_cb_t cb);
9091
void cw_enable_outputs(uint8_t enable_what);

0 commit comments

Comments
 (0)