@@ -38,6 +38,7 @@ pub const InterruptOptions = microzig.utilities.GenerateInterruptOptions(&.{
3838 .{ .InterruptEnum = enum { Exception }, .HandlerFn = InterruptHandler },
3939 .{ .InterruptEnum = Interrupt , .HandlerFn = InterruptHandler },
4040});
41+ const VectorTable = [vector_table_size ()]InterruptHandler ;
4142
4243pub const interrupt = struct {
4344 pub inline fn globally_enabled () bool {
@@ -69,7 +70,12 @@ pub const interrupt = struct {
6970 pub inline fn enable (irq : Interrupt ) void {
7071 comptime {
7172 const irq_name = @tagName (irq );
72- if (@field (microzig .options .interrupts , irq_name ) == null ) {
73+ const app_has = @field (microzig .options .interrupts , irq_name ) != null ;
74+ const hal_has = if (microzig .config .has_hal and @hasDecl (microzig .hal , "default_interrupts" ))
75+ @field (microzig .hal .default_interrupts , irq_name ) != null
76+ else
77+ false ;
78+ if (! app_has and ! hal_has ) {
7379 @compileError (
7480 irq_name ++ " interrupt handler should be defined.\n " ++
7581 "Add to your main file:\n " ++
@@ -327,14 +333,15 @@ fn vector_table_size() usize {
327333 return last_interrupt_idx + 1 - vector_table_offset ;
328334}
329335
330- pub fn generate_vector_table () [ vector_table_size ()] InterruptHandler {
336+ pub fn generate_vector_table () VectorTable {
331337 @setEvalBranchQuota (100_000 );
338+ var tmp : VectorTable = @splat (microzig .options .interrupts .Exception orelse unhandled );
332339
333340 const type_info = @typeInfo (Interrupt );
334341 const interrupts_list = type_info .@"enum" .fields ;
335342
336- var temp : [ vector_table_size ()] InterruptHandler = @splat ( microzig . options . interrupts . Exception orelse unhandled );
337- for (& temp , vector_table_offset .. ) | _ , idx | {
343+ // Apply interrupts
344+ for (& tmp , vector_table_offset .. ) | _ , idx | {
338345 // Find name of the interrupt by its number.
339346 var name : ? [:0 ]const u8 = null ;
340347 for (interrupts_list ) | decl | {
@@ -345,13 +352,33 @@ pub fn generate_vector_table() [vector_table_size()]InterruptHandler {
345352 }
346353
347354 if (name ) | n | {
348- if (@field (microzig .options .interrupts , n )) | h | {
349- temp [idx - vector_table_offset ] = h ;
350- }
355+ const maybe_handler = @field (microzig .options .interrupts , n );
356+ const maybe_default = get_hal_default_handler (n );
357+
358+ tmp [idx - vector_table_offset ] = blk : {
359+ if (maybe_handler ) | handler | {
360+ if (! microzig .options .overwrite_hal_interrupts and maybe_default != null )
361+ @compileError (std .fmt .comptimePrint (
362+ \\Interrupt {s} is used internally by the HAL; overriding it may cause malfunction.
363+ \\If you are sure of what you are doing, set "overwrite_hal_interrupts" to true in: "microzig_options".
364+ \\
365+ , .{n }));
366+ break :blk handler ;
367+ } else break :blk maybe_default orelse unhandled ;
368+ };
351369 }
352370 }
353371
354- return temp ;
372+ return tmp ;
373+ }
374+
375+ fn get_hal_default_handler (comptime handler_name : []const u8 ) ? InterruptHandler {
376+ if (microzig .config .has_hal ) {
377+ if (@hasDecl (microzig .hal , "default_interrupts" )) {
378+ return @field (microzig .hal .default_interrupts , handler_name );
379+ }
380+ }
381+ return null ;
355382}
356383
357384const vector_table = generate_vector_table ();
@@ -452,4 +479,9 @@ pub const csr = struct {
452479 pub const cpmpocr = Csr (0xBC3 , u32 );
453480 pub const cmcr = Csr (0xBD0 , u32 );
454481 pub const cinfor = Csr (0xFC0 , u32 );
482+
483+ // Cycle counters
484+ pub const cycle = riscv32_common .csr .cycle ;
485+ pub const cycleh = riscv32_common .csr .cycleh ;
486+ pub const mcountinhibit = riscv32_common .csr .mcountinhibit ;
455487};
0 commit comments