Commit a2f5c26a authored by Daniel Friesel's avatar Daniel Friesel
Browse files

Add transaction object with retry/abort functions

parent 6e43e8e9
Loading
Loading
Loading
Loading
+19 −29
Original line number Diff line number Diff line
@@ -8,37 +8,31 @@
#endif

extern "C" {
	void asm_save_toc();
	void asm_load_toc();
	void asm_save_all();
	void asm_load_all();
	void asm_load_mem();
}

volatile bool __attribute__((section(".text"))) have_state = false;
uint16_t i = 0;

void restore_state()
{
	if (!have_state) {
		return;
	}
	asm_load_toc();
}

void save_state()
{
	asm_save_toc();
	have_state = true;
}
class Transaction {
	public:
		inline Transaction() { asm_save_all(); }
		inline ~Transaction() {}
		inline void retry() { asm_load_all(); }
		inline void abort() { asm_load_mem(); }
};

void loop(void)
{
	gpio.led_toggle(1);
	{
		Transaction tx;
		kout << dec << i << endl;
		i++;
	if (i == 5) {
		save_state();
		if (!gpio.read(GPIO::p4_5)) {
			tx.abort();
		}
	if (i == 10) {
		restore_state();
	}
}

@@ -48,15 +42,11 @@ int main(void)
	gpio.setup();
	kout.setup();

	restore_state();
	//restore_state();

	gpio.led_on(0);
	gpio.input(GPIO::p4_5, 1);
	kout << "Hello, World!" << endl;
	kout << "Test, World!" << endl;
	kout << dec << uptime.get_cycles() << endl;
	kout << dec << uptime.get_cycles() << endl;
	kout << dec << uptime.get_cycles() << endl;
	kout << dec << uptime.get_cycles() << endl;

	arch.idle_loop();

+50 −6
Original line number Diff line number Diff line
.global asm_save_toc
.global asm_load_toc
.global asm_save_all
.global asm_load_all
.global asm_load_mem

stack_backup:
    .space 2048
@@ -7,7 +8,8 @@ stack_backup:
sp_backup:
    .space 2

asm_save_toc:
asm_save_all:
    dint
    .irp reg,4,5,6,7,8,9,10,11
    push r\reg
    .endr
@@ -26,21 +28,63 @@ save_sram_word:
    pop r11
    pop r10
    add #12, r1
    eint
    ret

asm_load_toc:
asm_load_all:
    dint

    ; restore SRAM from backup
    mov #stack_backup, r10
    mov #1c00h, r11

load_sram_word:
    mov @r10+, 0(r11)
    add #2, r11
    cmp #1c00h+2048, r11
    jlo load_sram_word

    ; restore stack pointer
    mov &sp_backup, r1

    ; restore registers
    .irp reg,11,10,9,8,7,6,5,4
    pop r\reg
    .endr

    eint

    ; The return address on the stack has been restored from FRAM backup
    ; -> execution will continue where asm_save_all was called
    ret

asm_load_mem:
    dint
    ; save return address in r4
    mov @r1, r4

    ; restore SRAM from backup
    mov #stack_backup, r10
    mov #1c00h, r11
load_sram_word2:
    mov @r10+, 0(r11)
    add #2, r11
    cmp #1c00h+2048, r11
    jlo load_sram_word2

    ; restore stack pointer
    mov &sp_backup, r1

    ; restore old register contents
    .irp reg,11,10,9,8,7,6,5
    pop r\reg
    .endr

    ; load return address, that is, the address this function was called from.
    ; This is not the address which called asm_save_all -- we only want to restore memory contents, not re-execute everything
    mov r4, 2(r1)

    ; load remaining register content
    pop r4

    eint
    ret