Skip to content

Commit 6c99069

Browse files
zelenskiCS107E BOT
authored andcommitted
Interrupts2 lecture
commit 0a905af3b19fc32250d07a783dc5f42d884a653c Author: Julie Zelenski <[email protected]> Date: Mon Nov 11 01:14:55 2024 -0800 Interrupts2 lecture
1 parent cad2da6 commit 6c99069

File tree

11 files changed

+390
-100
lines changed

11 files changed

+390
-100
lines changed

_data/unreleased.csv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
permalink,title,released
22
"/assignments/assign7/","Assignment 7: System Monitor with Interrupts",false
33
"/project/","Final Project",false
4-
"/labs/lab7/","Lab 7: Mango Pi, Interrupted",false
54
"/labs/projectlab1/","Lab 8: Project Team Meeting 1",false
65
"/labs/projectlab2/","Lab 9: Project Team Meeting 2",false
76
"/lectures/FloatingPoint_Sound/","Floating Point and Sound",false

cs107e/lib/libmango.a

0 Bytes
Binary file not shown.

cs107e/src/gpio_interrupt.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,8 @@ static gpio_int_group_t *get_int_group(gpio_id_t gpio, int *p_index) {
5858
return &module.groups[p.group];
5959
}
6060

61-
// register dispatch_to_pin with top-level interrupts module
62-
// as handler for all GPIO interrupt sources
63-
// Aux data will be pointer to interrupt group
61+
// register private function dispatch_to_pin with top-level interrupts module
62+
// as handler for all GPIO interrupt sources, use pointer to interrupt group as aux_data
6463
void gpio_interrupt_init(void) {
6564
for (int i = 0; i < GPIO_NGROUPS; i++) {
6665
interrupts_register_handler(module.groups[i].source, dispatch_to_pin, &module.groups[i]);
@@ -82,6 +81,8 @@ void gpio_interrupt_register_handler(gpio_id_t gpio, handlerfn_t fn, void *aux_d
8281
// per-pin handlers that have been registered with this module
8382
static void dispatch_to_pin(void *aux_data) {
8483
gpio_int_group_t *gp = aux_data;
84+
// find 'on' bit in status register to determine which pin had interrupt
85+
// use clz to count number of leading zero bits before first one bit
8586
int pin_index = 31 - __builtin_clz(gp->eint->regs.status);
8687
gp->handlers[pin_index].fn(gp->handlers[pin_index].aux_data);
8788
}
@@ -93,9 +94,9 @@ static void gpio_interrupt_set_enabled(gpio_id_t gpio, bool state) {
9394
gpio_int_group_t *gp = get_int_group(gpio, &pin_index);
9495
unsigned int mask = (1 << pin_index);
9596
if (state) {
96-
gp->eint->regs.ctl |= mask;
97+
gp->eint->regs.ctl |= mask; // set enable bit
9798
} else {
98-
gp->eint->regs.ctl &= ~mask;
99+
gp->eint->regs.ctl &= ~mask; // clear enable bit
99100
}
100101
}
101102

@@ -113,8 +114,8 @@ void gpio_interrupt_clear(gpio_id_t gpio) {
113114
int pin_index;
114115
gpio_int_group_t *gp = get_int_group(gpio, &pin_index);
115116
unsigned int mask = (1 << pin_index);
116-
if ((gp->eint->regs.status & mask) != 0) { // is pending
117-
gp->eint->regs.status |= mask; // write 1 to clear
117+
if ((gp->eint->regs.status & mask) != 0) { // if pending bit set for this pin
118+
gp->eint->regs.status |= mask; // write 1 to clear
118119
}
119120
}
120121

@@ -129,12 +130,12 @@ void gpio_interrupt_config(gpio_id_t gpio, gpio_event_t event, bool debounce) {
129130
unsigned int mask = ((1 << 4) - 1);
130131
gp->eint->regs.cfg[bank] = (gp->eint->regs.cfg[bank] & ~(mask << shift)) | ((event & mask) << shift);
131132
gpio_set_function(gpio, GPIO_FN_INTERRUPT); // change pin function to interrupt
132-
if (debounce) {
133-
// 32Khz clock, predivide 2^5, will filter to ~1 event per ms
133+
if (debounce) { // if debounce requested
134+
// apply 32Khz clock, predivide 2^5, will filter to ~1 event per ms
134135
gp->eint->regs.debounce = (5 << 4) | 0;
135136
} else {
136-
// 24Mhz clock, no predivide, no filter
137+
// apply 24Mhz clock, no predivide, no filter
137138
gp->eint->regs.debounce = (0 << 4) | 1;
138139
}
139-
gpio_interrupt_clear(gpio); // cancel any stale event
140+
gpio_interrupt_clear(gpio); // clear any past event, start anew with updated config
140141
}

cs107e/src/hstimer.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ typedef union {
1313
struct {
1414
uint32_t ctrl;
1515
uint32_t intv_lo; // lower 32 bits of interval (see docs note above)
16-
uint32_t intv_hi; // uppper 32 bits of interval
16+
uint32_t intv_hi; // upper 32 bits of interval
1717
uint32_t cur_lo; // lower 32 bits of cur value
1818
uint32_t cur_hi; // upper 32 bits of cur value
1919
} regs;
@@ -50,23 +50,23 @@ static struct {
5050
*/
5151
void hstimer_init(hstimer_id_t index, long usecs) {
5252
if (index != HSTIMER0 && index != HSTIMER1) return;
53-
long rate = ccu_ungate_bus_clock(CCU_HSTIMER_BGR_REG); // clock up peripheral
54-
module.timers[index].regs.ctrl = (0 << 7) | (0 << 4); // config for normal mode, periodic (not one-shot), prescale = 2^0, disabled
55-
uint64_t count = (usecs * rate)/(1000*1000); // calculate count based on clock frequency
53+
long rate = ccu_ungate_bus_clock(CCU_HSTIMER_BGR_REG); // clock up peripheral
54+
module.timers[index].regs.ctrl = (0 << 7) | (0 << 4); // config mode normal periodic (not one-shot), prescale = 2^0, not enabled
55+
uint64_t count = (usecs * rate)/(1000*1000); // calculate count based on clock frequency
5656
module.timers[index].regs.intv_lo = count & 0xffffffff; // must set low before high (see docs note above)
5757
module.timers[index].regs.intv_hi = count >> 32;
58-
module.timers[index].regs.ctrl |= (1 << 1); // reload interval into cur
58+
module.timers[index].regs.ctrl |= (1 << 1); // reload interval into cur
5959
module.interrupt->regs.irq_en |= (1 << index); // enable interrupts
6060
}
6161

6262
void hstimer_enable(hstimer_id_t index) {
6363
if (index != HSTIMER0 && index != HSTIMER1) return;
64-
module.timers[index].regs.ctrl |= 1; // enable will start (or resume) countdown
64+
module.timers[index].regs.ctrl |= 1; // set ctrl bit will start/resume countdown
6565
}
6666

6767
void hstimer_disable(hstimer_id_t index) {
6868
if (index != HSTIMER0 && index != HSTIMER1) return;
69-
module.timers[index].regs.ctrl &= ~1; // disable will pause countdown
69+
module.timers[index].regs.ctrl &= ~1; // clear ctrl bit will pause countdown
7070
}
7171

7272
void hstimer_interrupt_clear(hstimer_id_t index) {

cs107e/src/interrupts.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ void interrupts_set_mtvec(void *);
2222
// structs defined to match layout of hardware registers
2323
typedef union {
2424
struct {
25-
uint32_t priority[1024]; // only first 256 used (N_SOURCES)
26-
uint32_t pending[1024]; // only first 8 used (one pending bit per source)
27-
uint32_t enable[1024]; // only first 8 used (one enable bit per source)
25+
uint32_t priority[1024]; // only first 256 indexes are used (priority per source)
26+
uint32_t pending[1024]; // only first 8 indexes used (pending bit per source, 256/32 = 8)
27+
uint32_t enable[1024]; // only first 8 indexes used (enable bit per source, 256/32 = 8)
2828
} regs;
2929
} source_t;
3030

@@ -85,10 +85,10 @@ __attribute__((interrupt("machine"))) void _trap_handler(void) {
8585
long mcause = interrupts_get_mcause();
8686
#define EXTERNAL_INTERRUPT ((1L << 63) | 0xb)
8787
if (mcause == EXTERNAL_INTERRUPT) { // trap is interrupt
88-
// no need to search pending bits to identify source, claim reg has it
88+
// do not need to search pending bits to identify which source, claim reg has source number
8989
uint32_t source = module.plic->regs.claim_complete; // read claim_complete to "claim" (atomically clears pending bit)
9090
module.handlers[source].fn(module.handlers[source].aux_data); // dispatch to registered handler
91-
module.plic->regs.claim_complete = source; // write claim_complete to "complete"
91+
module.plic->regs.claim_complete = source; // write claim_complete to clear
9292
} else { // trap is exception
9393
long mtval = interrupts_get_mtval();
9494
void *mepc = (void *)interrupts_get_mepc();
@@ -110,17 +110,17 @@ __attribute__((interrupt("machine"))) void _trap_handler(void) {
110110
void interrupts_init(void) {
111111
if (module.initialized) error("interrupts_init() must be called only once");
112112
interrupts_global_disable();
113-
module.plic->regs.ctrl = 0; // machine mode only
114-
module.plic->regs.threshhold = 0; // accept interrupts of any priority
115-
interrupts_set_mtvec(_trap_handler); // install trap handler
116-
for (int i = 0; i < 8; i++) { // all sources start disabled
117-
module.sources->regs.pending[i] = 0;
113+
module.plic->regs.ctrl = 0; // machine mode only
114+
module.plic->regs.threshhold = 0; // accept interrupts of any priority
115+
interrupts_set_mtvec(_trap_handler); // install trap handler
116+
for (int i = 0; i < N_SOURCES/32; i++) {
117+
module.sources->regs.pending[i] = 0;// all sources initially disabled
118118
module.sources->regs.enable[i] = 0;
119119
}
120120
for (int i = 0; i < N_SOURCES; i++) {
121121
module.sources->regs.priority[i] = 0;
122-
module.handlers[i].fn = NULL;
123-
module.plic->regs.claim_complete = i; // mark any pending request completed
122+
module.handlers[i].fn = NULL; // all sources initially have NULL handler
123+
module.plic->regs.claim_complete = i; // reset any pending claim
124124
}
125125
module.initialized = true;
126126
}
@@ -144,10 +144,10 @@ static void set_source_enabled(interrupt_source_t source, bool enabled) {
144144
int shift = source % 32;
145145
if (enabled) {
146146
module.sources->regs.priority[source] = 1; // priority at 1 (0 is disable, 1 is lowest)
147-
module.sources->regs.enable[bank] |= (1 << shift);
147+
module.sources->regs.enable[bank] |= (1 << shift); // set enable bit
148148
} else {
149149
module.sources->regs.priority[source] = 0;
150-
module.sources->regs.enable[bank] &= ~(1 << shift);
150+
module.sources->regs.enable[bank] &= ~(1 << shift); // clear enable bit
151151
}
152152
}
153153

@@ -162,6 +162,6 @@ void interrupts_disable_source(interrupt_source_t source) {
162162
void interrupts_register_handler(interrupt_source_t source, handlerfn_t fn, void *aux_data) {
163163
if (!module.initialized) error("interrupts_init() has not been called!\n");
164164
if (!is_valid_source(source)) error("request to register handler for interrupt source that is not valid");
165-
module.handlers[source].fn = fn;
166-
module.handlers[source].aux_data = aux_data;
165+
module.handlers[source].fn = fn; // store handler function and
166+
module.handlers[source].aux_data = aux_data; // aux_data pointer into array at index corresponding to source
167167
}

cs107e/src/interrupts_asm.s

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,36 @@
55

66
.globl interrupts_global_enable
77
interrupts_global_enable:
8-
li a0,1<<3
9-
csrs mstatus,a0
10-
li a0,1<<11
11-
csrs mie,a0
8+
li a0,1<<11 # MEIE bit 11 (m-mode external interrupts)
9+
csrs mie,a0 # set bit in mie register
10+
li a0,1<<3 # MIE bit 3 (global enable m-mode interrupts)
11+
csrs mstatus,a0 # set bit in mstatus register
1212
ret
1313

1414
.globl interrupts_global_disable
1515
interrupts_global_disable:
16+
li a0,1<<11 # (reverse steps from global enable)
17+
csrc mie,a0 # clear bit in mie
1618
li a0,1<<3
17-
csrc mstatus,a0
18-
li a0,1<<11
19-
csrc mie,a0
19+
csrc mstatus,a0 # clear bit in mstatus
2020
ret
2121

2222
.globl interrupts_get_mcause
2323
interrupts_get_mcause:
24-
csrr a0,mcause
24+
csrr a0,mcause # retrieve mcause
2525
ret
2626

2727
.globl interrupts_get_mepc
2828
interrupts_get_mepc:
29-
csrr a0,mepc
29+
csrr a0,mepc # retrieve mepc
3030
ret
3131

3232
.globl interrupts_get_mtval
3333
interrupts_get_mtval:
34-
csrr a0,mtval
34+
csrr a0,mtval # retrieve mtval
3535
ret
3636

3737
.globl interrupts_set_mtvec
3838
interrupts_set_mtvec:
39-
csrw mtvec,a0
39+
csrw mtvec,a0 # mtvec holds addr of handler to call on trap
4040
ret

cs107e/src/ringbuffer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Both head and tail advance circularly, i.e. index = (index + 1) % LENGTH
2323
* The ring buffer is empty if tail == head
2424
* The ring buffer is full if tail + 1 == head
25-
* (Note: one slot remains permanently empty to distinguish full from empty)
25+
* (Note: one slot permanently unused to distinguish full from empty)
2626
*/
2727

2828
struct ringbuffer {

0 commit comments

Comments
 (0)