Skip to content

Commit

Permalink
Added: Timer0 (8-bit) + IRQs
Browse files Browse the repository at this point in the history
  • Loading branch information
Milo-D committed Sep 27, 2020
1 parent 2b7dece commit 4df6218
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 37 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@

## Unreleased

- Peripheral: Timer0 (8-bit) is now supported.
- Supported Prescaling: 1/8/64/256/1024
- Supported Mode: Normal Mode
- Currently not supported: PWM and external clock select

- Timer interrupts are now available.

- Added new assembly instructions:
- lpm(R0) (load program memory)
- lpm(Z) (load program memory)
- call (32-bit call)
- las (load and set byte in data space)
- lac (load and clear byte in data space)
- fmul (fractional multiply unsigned)
- reti (return from interrupt)

- Bug fix for the preprocessor
- Skip instructions are now compatible with 32-bit opcode
- Jumps, skips, etc. are now able to wrap around FLASH memory

- Refactored System class (Core / Peripherals)
- Seperate IO space class
- IRQ Handler

## v.0.0.2 - 2020-09-17

- 32-bit Decoder: 32-bit opcodes are now supported
Expand Down
37 changes: 21 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,26 +153,31 @@ Note: You may open multiple files in interactive Debugging Mode.
- [ ] ...

# Features
- [x] Debugging Assembly
- [x] Advanced Disassembler, recovering Labels
- [x] Backwards Stepping
- [x] Simple and fancy Commandline Design
- [x] GPR Visualization
- [x] SRAM Visualization
- [x] Loading .eep.hex into the Microcontroller
- [ ] EEPROM Visualization
- [x] SREG Visualization
- [ ] FLASH Visualization
- [ ] Relation between Code Segments
- [ ] I/O Support
- [ ] Seperate I/O Pin View
- [x] Advanced Disassembler, recovering Labels
- [x] Syntax Highlight for the disassembled Sourcecode
- [x] Interrupts supported
- [x] Open and debug more than one file in the same session
- [x] Fast and easy to use
- [x] Short CLI Commands to debug faster
- [ ] Full Instruction Support
- [ ] Currently supporting ~ 93 assembly instructions

- [x] Breakpoints
- [ ] Watchpoints
- [x] Examine Memory

- [x] Interactive Mode
- [x] Disassembler Mode
- [x] Headless Mode

- [ ] Peripherals
- [x] 8-bit Timer (partial)
- [ ] 16-bit Timer
- [ ] EEPROM
- [ ] UART
- [ ] SPI
- [ ] ...

# Instructions
Currently MDX supports: ~ 72 Instructions. More Instructions are coming soon.
Currently MDX supports: ~ 93 Instructions. More Instructions are coming soon.

# Contributing

Expand Down
2 changes: 1 addition & 1 deletion include/misc/mnemstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#define N_MAPS 6

#define N_FLOW 19
#define N_FLOW 20
#define N_MISC 21
#define N_LOGIC 14
#define N_ACCESS 13
Expand Down
1 change: 0 additions & 1 deletion include/system/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ extern void sys_dump_data(const struct _system *this, array_t *buffer);
/* IO Operations */

extern void sys_update_io(const struct _system *this, const uint64_t oldc);
extern void sys_exec_irs(struct _system *this, const int isr);

/* EEPROM Operations */

Expand Down
4 changes: 2 additions & 2 deletions src/disassembler/labelmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ struct _lmap* lmap_ctor(void) {
lmap->p->labels = array_ctor(256, NULL, NULL);
lmap->p->map = strmap_ctor(N_FLOW);

for(int i = 0; i < N_FLOW - 3; i++) {
for(int i = 0; i < N_FLOW - 4; i++) {

/* (N_FLOW - 3) excludes indirect jumps */
/* (N_FLOW - 4) excludes indirect jumps */

const char *instr = mnemstr[FLOW][i];
strmap_put(lmap->p->map, mnemstr[FLOW][i]);
Expand Down
19 changes: 17 additions & 2 deletions src/disassembler/mnemonics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1490,6 +1490,21 @@ char* mnem_ret(const int opcode) {
return mnemonic;
}

char* mnem_reti(const int opcode) {

queue_t *stream = queue_ctor();

char *fill = strfill(' ', 4, TAB);
queue_put(stream, 3, "reti", fill, "; PC <- DATA[SP]");

char *mnemonic = queue_str(stream);

queue_dtor(stream);
free(fill);

return mnemonic;
}

char* mnem_icall(const int opcode) {

queue_t *stream = queue_ctor();
Expand Down Expand Up @@ -2258,8 +2273,8 @@ char* (*mnemonics[INSTR_MAX]) (const int opcode) = {
mnem_dec, mnem_inc, mnem_add, mnem_adc, mnem_adiw, mnem_sub, mnem_subi, mnem_sbc, mnem_sbci, mnem_sbiw, mnem_push, mnem_pop,
mnem_in, mnem_out, mnem_sbis, mnem_sbrc, mnem_clr, mnem_ld_x, mnem_ld_xi, mnem_ld_dx, mnem_ld_y, mnem_ld_yi, mnem_ld_dy, mnem_ldd_yq,
mnem_ldd_zq, mnem_ld_z, mnem_ld_zi, mnem_st_x, mnem_st_xi, mnem_std_yq, mnem_std_zq, mnem_sts, mnem_sts32, mnem_xch, mnem_brne, mnem_breq,
mnem_brge, mnem_brpl, mnem_brlo, mnem_brlt, mnem_brcc, mnem_brcs, mnem_brvs, mnem_brts, mnem_brtc, mnem_brmi, mnem_rcall, mnem_ret, mnem_icall, mnem_call,
mnem_cp, mnem_cpi, mnem_cpc, mnem_lsr, mnem_asr, mnem_ror, mnem_swap, mnem_ori, mnem_or_asm, mnem_and_asm, mnem_andi, mnem_las, mnem_lac, mnem_com, mnem_neg,
mnem_brge, mnem_brpl, mnem_brlo, mnem_brlt, mnem_brcc, mnem_brcs, mnem_brvs, mnem_brts, mnem_brtc, mnem_brmi, mnem_rcall, mnem_ret, mnem_reti, mnem_icall,
mnem_call, mnem_cp, mnem_cpi, mnem_cpc, mnem_lsr, mnem_asr, mnem_ror, mnem_swap, mnem_ori, mnem_or_asm, mnem_and_asm, mnem_andi, mnem_las, mnem_lac, mnem_com, mnem_neg,
mnem_bld, mnem_bst, mnem_lpm, mnem_lpm_z, mnem_ses, mnem_set, mnem_sev, mnem_sez, mnem_seh, mnem_sec, mnem_sei, mnem_sen, mnem_cls, mnem_clt, mnem_clv,
mnem_clz, mnem_clh, mnem_clc, mnem_cli, mnem_cln, mnem_bclr, mnem_bset
};
Expand Down
1 change: 1 addition & 0 deletions src/disassembler/opcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const int opcode[SET_SIZE][WORD] = {
{ 1, 1, 1, 1, 0, 0, K, K, K, K, K, K, K, 0, 1, 0 }, /* BRMI */
{ 1, 1, 0, 1, K, K, K, K, K, K, K, K, K, K, K, K }, /* RCALL */
{ 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 }, /* RET */
{ 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0 }, /* RETI */
{ 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1 }, /* ICALL */
{ 1, 0, 0, 1, 0, 1, 0, K, K, K, K, K, 1, 1, 1, K }, /* CALL */
{ 0, 0, 0, 1, 0, 1, R, D, D, D, D, D, R, R, R, R }, /* CP */
Expand Down
28 changes: 26 additions & 2 deletions src/instructions/instructions.c
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,30 @@ void ret(system_t *sys, const int opcode) {
}
}

void reti(system_t *sys, const int opcode) {

uint8_t pcl, pch, pcm;

switch(PC_BIT) {

case 16:

pch = sys_pop_stack(sys);
pcl = sys_pop_stack(sys);

sys_set_pc(sys, (pch << 8) + pcl);
sys->cycles += 4;

break;

case 22: /* currently not supported */ break;

default: return;
}

sys_write_sreg(sys, IF, 0x01);
}

void icall(system_t *sys, const int opcode) {

const int pc = sys_get_pc(sys);
Expand Down Expand Up @@ -1848,8 +1872,8 @@ void (*instructions[INSTR_MAX]) (system_t *sys, const int opcode) = {
dec, inc, add, adc, adiw, sub, subi, sbc, sbci, sbiw, push, pop,
in, out, sbis, sbrc, clr, ld_x, ld_xi, ld_dx, ld_y, ld_yi, ld_dy, ldd_yq,
ldd_zq, ld_z, ld_zi, st_x, st_xi, std_yq, std_zq, sts, sts32, xch, brne, breq,
brge, brpl, brlo, brlt, brcc, brcs, brvs, brts, brtc, brmi, rcall, ret, icall, call,
cp, cpi, cpc, lsr, asr, ror, swap, ori, or_asm, and_asm, andi, las, lac, com, neg,
brge, brpl, brlo, brlt, brcc, brcs, brvs, brts, brtc, brmi, rcall, ret, reti, icall,
call, cp, cpi, cpc, lsr, asr, ror, swap, ori, or_asm, and_asm, andi, las, lac, com, neg,
bld, bst, lpm, lpm_z, ses, set, sev, sez, seh, sec, sei, sen, cls, clt, clv,
clz, clh, clc, cli, cln, bclr, bset
};
Expand Down
2 changes: 1 addition & 1 deletion src/misc/mnemstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const char *mnemstr[N_MAPS][32] = {
/* Flow Mnemonics */
{ "rjmp", "brne", "breq", "brge", "brpl", "brlo", "brlt", "brcc",
"brcs", "brvs", "brts", "brtc", "brmi", "rcall", "jmp", "call", "ret",
"icall", "ijmp" },
"icall", "ijmp", "reti" },

/* Misc Mnemonics */
{ "nop", "bld", "bst", "ses", "set", "sev", "sez", "seh", "sec", "sei", "sen",
Expand Down
36 changes: 24 additions & 12 deletions src/system/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ struct _private {
bool terminated;
};

/* Forward Declaration of static Functions */

static void sys_exec_irs(struct _system *this, const int isr);

/* --- Extern --- */

struct _system* sys_ctor(const char *file) {

struct _system *sys;
Expand Down Expand Up @@ -95,7 +101,7 @@ int sys_step(struct _system *this) {

sys_update_io(this, old_cycles);

if((sreg & (0x01 << IF)) == 0x01) {
if((sreg & (0x01 << IF)) != 0x00) {

int isr;

Expand Down Expand Up @@ -252,17 +258,6 @@ void sys_update_io(const struct _system *this, const uint64_t oldc) {
data_update_io(this->p->data, this->clock, (this->cycles - oldc));
}

void sys_exec_irs(struct _system *this, const int isr) {

const uint64_t old_cycles = this->cycles;
this->cycles += 4;

alu_write_sreg(this->p->alu, IF, 0);
sys_update_io(this, old_cycles);

alu_set_pc(this->p->alu, isr);
}

void sys_write_eeprom(struct _system *this, const uint16_t addr, const int8_t value) {

eeprom_write(this->p->eeprom, addr, value);
Expand Down Expand Up @@ -307,3 +302,20 @@ entry_t* sys_dump_table(const struct _system *this) {

return alu_dump_table(this->p->alu);
}

/* --- Static --- */

static void sys_exec_irs(struct _system *this, const int isr) {

const uint64_t old_cycles = this->cycles;
const int pc = alu_get_pc(this->p->alu);

data_push(this->p->data, pc & 0x00ff);
data_push(this->p->data, (pc & 0xff00) >> 8);

alu_write_sreg(this->p->alu, IF, 0x00);
this->cycles += 4;

sys_update_io(this, old_cycles);
alu_set_pc(this->p->alu, isr);
}
66 changes: 66 additions & 0 deletions test/peripherals/timer0/timer0_8bit.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
.INCLUDE "m32def.inc"

;
; Demonstrating 8-bit Timer0 in ATmega32.
;
; MDX is now able to simulate hardware timers
; and interrupts. Currently, only timer0
; (TCNT0) is available and PWM is not supported.
; But I am working on it ;)
;
; The following program initialize TCNT0, and
; enables Hardware Interrupts (TOIE0 in TIMSK).
; Whenever an overflow in TCNT0 occurs, the
; ISR (isr_tim0_ov) is executed. The ISR is
; writing to PORTB.
;
; Mode: Timer0 (8-bit), Normal Mode
; Prescaler: clk(cpu) / 1
;
; This program was successfully simulated by MDX.
;


.def temp = r18

.ORG 0x0000
rjmp stack_init

.ORG OVF0addr
rjmp isr_tim0_ov

stack_init:
ldi temp, LOW(RAMEND)
out SPL, temp
ldi temp, HIGH(RAMEND)
out SPH, temp
rjmp port_init

port_init:
ldi r17, 0xff
out DDRB, r17
out PORTB, r17
rjmp enable_irq

enable_irq:
ldi r16, 0x01
out TIMSK, r16
sei
rjmp enable_timer

enable_timer:
ldi r16, (0x01 << CS00)
out TCCR0, r16
rjmp loop

loop:
rjmp loop

; ISR (Timer0 Overflow)

isr_tim0_ov:
out PORTB, r17
com r17
reti


6 changes: 6 additions & 0 deletions test/peripherals/timer0/timer0_8bit.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:020000020000FC
:0200000016C028
:10002C0011C02FE52DBF28E02EBF00C01FEF17BB5E
:10003C0018BB00C001E009BF789400C001E003BF09
:0A004C0000C0FFCF18BB10951895F7
:00000001FF

0 comments on commit 4df6218

Please sign in to comment.