stack void *sp; asm("mv %0, sp" : "=r"(sp)); CRITICAL("%p", sp); --- register handler asm("csrw mtvec, %0" ::"r"(handler)); --- helper functions #define CLINT0_MTIME 0x200bff8 #define CLINT0_MTIMECMP 0x2004000 unsigned long long mtime_get() { unsigned int low = *(unsigned int*)(CLINT0_MTIME); unsigned int high = *(unsigned int*)(CLINT0_MTIME + 4); return (((unsigned long long)high) << 32) | (unsigned long long)low; } void mtimecmp_set(unsigned long long time) { *(unsigned int*)(CLINT0_MTIMECMP + 0) = (unsigned int)time; *(unsigned int*)(CLINT0_MTIMECMP + 4) = (unsigned int)(time >> 32); } --- set timer mtimecmp_set(mtime_get() + QUANTUM); --- enable timer interrupt int mstatus, mie; asm("csrr %0, mstatus" : "=r"(mstatus)); asm("csrw mstatus, %0" ::"r"(mstatus | 0x8)); asm("csrr %0, mie" : "=r"(mie)); asm("csrw mie, %0" ::"r"(mie | 0x80)); --- union union tmp { int num; char chars[4]; }; union tmp u = {0}; u.num = 0x41; // ascii, 'A' CRITICAL("%s\n", u.chars); --- string 1 u.num = (0x41 << 8); // ascii, 'A' --- string 2 u.num = (0x41 << 8) + 0x42; // ascii, 'A' --- [skipped] resilient to overflow static unsigned long long mtime_get() { unsigned int low, high; /* Q: Why having a loop? */ do { high = *(unsigned int*)(CLINT0_MTIME + 4); low = *(unsigned int*)(CLINT0_MTIME); } while ( *(unsigned int*)(CLINT0_MTIME + 4) != high ); return (((unsigned long long)high) << 32) | (unsigned long long)low; } /* set "mtimecmp" to "time" */ static void mtimecmp_set(unsigned long long time) { /* Q: Why setting mtimecmp low to all 0xF? */ *(unsigned int*)(CLINT0_MTIMECMP + 4) = 0xFFFFFFFF; *(unsigned int*)(CLINT0_MTIMECMP + 0) = (unsigned int)time; *(unsigned int*)(CLINT0_MTIMECMP + 4) = (unsigned int)(time >> 32); }