void timer_write( unsigned int address, unsigned int value) { //printf("Timer write, 0x%08x = 0x%08x\n",address,value); switch(address& 0xF) { case 0: ctrl = value; /* printf("Timer bits: EN %d CCM %d DIR %d IEN %d\n", !!(ctrl & BIT(TCTLENA)), !!(ctrl & BIT(TCTLCCM)), !!(ctrl & BIT(TCTLDIR)), !!(ctrl & BIT(TCTLIEN))); */ switch (bit_range(ctrl,6,4)) { case 0: timer_prescaler=0; break; case 1: timer_prescaler=1; break; case 2: timer_prescaler=2; break; case 3: timer_prescaler=4; break; case 4: timer_prescaler=8; break; case 5: timer_prescaler=32; break; case 6: timer_prescaler=128; break; case 7: timer_prescaler=512; break; } //printf("Timer prescaler is now %d\n",timer_prescaler); timer_prescaleCount=0; break; case 4: // Counter printf("# Timer: set counter to %04x\n",value); timer_cnt = value & 0xffff; break; case 8: // Compare printf("Timer: set compare to %04x\n",value); timer_match = value & 0xffff; break; case 12: // Compare break; } }
void timer_write( unsigned int address, unsigned int value) { //zpudebug("Timer write, 0x%08x = 0x%08x\n",address,value); int reset_thread=0; switch(address & 0xF) { case 0: ctrl = value; /* printf("Timer bits: EN %d CCM %d DIR %d IEN %d\n", !!(ctrl & BIT(TCTLENA)), !!(ctrl & BIT(TCTLCCM)), !!(ctrl & BIT(TCTLDIR)), !!(ctrl & BIT(TCTLIEN))); */ switch (bit_range(ctrl,6,4)) { case 0: timer_prescaler=0; break; case 1: timer_prescaler=1; break; case 2: timer_prescaler=2; break; case 3: timer_prescaler=4; break; case 4: timer_prescaler=8; break; case 5: timer_prescaler=32; break; case 6: timer_prescaler=128; break; case 7: timer_prescaler=512; break; } //printf("Timer prescaler is now %d\n",timer_prescaler); timer_prescaleCount=0; break; case 4: // Counter //printf("# Timer: set counter to %04x\n",value); timer_cnt = value & 0xffff; reset_thread=1; break; case 8: // Compare //printf("Timer: set compare to %04x\n",value); timer_match = value & 0xffff; reset_thread=1; break; case 12: break; } // Compute wall time. if (ctrl & BIT(TCTLENA) && ctrl & BIT(TCTLCCM) && ctrl & BIT(TCTLDIR) && ctrl & BIT(TCTLIEN)) { //fprintf(stderr,"TIMER: Using wall clock for timer interrupt\n"); // Compute delay unsigned long long cl = zpuinoclock / (timer_prescaler? (timer_prescaler<<1) : 1); unsigned long long count = (timer_match+1); count *= 1000000000ULL; count/=cl; //fprintf(stderr,"Timer delay is %llu nanoseconds\n",count); sleepreq.tv_sec = count/1000000000; sleepreq.tv_nsec = count% 1000000000; if (threadid==-1 || reset_thread) stop_start_thread(); } else { if (!(ctrl&BIT(TCTLENA) & (ctrl&BIT(TCTLIEN)))) { // Cancel thread cancel_thread(); } } }