// TimerTest for Nios II -- Bruce Land 3july2006 //I like these: #define begin { #define end } //from http://www.cc65.org/faq.php#PeekPoke #define POKE(addr,val) (*(unsigned char*) (addr) = (val)) #define POKEW(addr,val) (*(unsigned*) (addr) = (val)) #define PEEK(addr) (*(unsigned char*) (addr)) #define PEEKW(addr) (*(unsigned*) (addr)) //Addresses from ptf file or SOPC interface #define switches 0x1820 #define LEDs 0x1830 //Timer description from http://altera.com/literature/hb/nios2/n2cpu_nii51008.pdf //NOTE--these are 16 bit registers, BUT offsets in the manual are in 32-bit chunks #define timer_status 0x1800 //bit1=RUN bit0=TO #define timer_control 0x1804 //bit3=STOP bit2=START bit1=CONT bit0=ITO #define timer_periodl 0x1808 //timer autoreloads these at count==zero #define timer_periodh 0x180c #define timer_snapl 0x1810 //a write causes timer copy here #define timer_snaph 0x1814 #define exception_addr 0x20 //contains: branch to the interrupt handler //Timer behavior: //TO bit is set by hardware when count==0 //uses ISR bit 1 (see configuration data in SOPC builder) //On interrupt, you must Clear the TO bit of the status register //RUN bit is read-only and is one when running //ITO bit enables the count==0 interrupt //START bit starts the timer when written with a 1 //STOP bit stops the timer when written with a 1 //CONT bit causes a periodic interrupt when 1 //for a 1 second period, 50e6 counts = 0x2FAF080 //For communication with ISR register int flag asm ("r23"); register int temp asm ("r22"); //Timer ISR static void TimerISR(void) begin //next two lines are: POKE(timer_status, 0); asm volatile ("orhi r22, r0, %hi(0x1800) \n ori r22, r22, %lo(0x1800"); asm volatile ("stbio r0, 0(r22)"); asm volatile ("xori r23, r23, 0xff"); //flag = flag ^ 0xff asm volatile ("subi r29, r29, 4"); //fix exception return address asm volatile ("eret"); //return from exception end //set up ISR, then //just read some switches and flash some lights main() begin char sw; //holds switch values void (*pISR) (void); //pointer to ISR function int BR_exception; //build a branch instruction as {(offset<<6) + 0x06} // set up timer ISR address // Skip first 3 instructions of function to jump over // the function init code generated by the compiler == 12 bytes pISR = &TimerISR + 0xc ; // Construct the instruction "br pISR" // offset IMM16 is relative to instruction following exception_addr // The shift 6 sends the offset to the correct bits // The last 0x06 is the opcode for BR BR_exception = (((int)pISR - exception_addr - 4) << 6 ) + 0x06 ; POKEW(exception_addr, BR_exception); //set up timer period to one second POKEW(timer_periodl, 0xf080); POKEW(timer_periodh, 0x2fa); //set up timer control: START timer, set CONT=1, and enable timer ITO bit POKE(timer_control, 7); //set up timer IRQ bit in the enable control register asm("movi r22, 2"); asm("wrctl ienable, r22"); //set up master interrupt bit in the cpu status register asm("movi r22, 1"); asm("wrctl status, r22"); //initialize LED inverting bits flag = 0xff; while(1) begin sw = PEEK(switches); //read from switches POKE(LEDs,sw^flag); //write to LEDs sw = 1; //defeats the optimizer end end