Buy an Axon, Axon II, or Axon Mote and build a great robot, while helping to support SoR.
0 Members and 1 Guest are viewing this topic.
void InitServoGroupMove(SERVO_LIST* servos, const TimerCompare* channel){ // Save away pointer to servos. s_msd.servos = servos; const Timer* timer = compareGetTimer(channel); if(timerIs16bit(timer)){ uint32_t tmp32; // Select a prescaler that is bigger than the biggest pause. // Added 5ms just in case other interrupts kick in. uint16_t prescale; // If the timer is already in use then make sure it uses the same mode if(timerIsInUse(timer)){ prescale = timerGetPrescaler(timer); if(timerGetMode(timer) != TIMER_MODE_NORMAL){ setError(PWM_TIMER_IN_USE); } }else{ prescale = timerGetBestPrescaler(timer, USPERMSERVOLOOP + 5 ); } // Find how many timer ticks there will be for USPERMSERVOLOOP tmp32 = ticks_per_ms(USPERMSERVOLOOP,prescale); s_msd.servo_cycle = tmp32; // make sure it fits if( (tmp32 & 0xFFFF0000UL)!=0){ setError(SERVO_TIMING); } // Set the threshold to start interrupt chain if(getError()==0){ compareAttach(channel, &__servoGMService, compareGetThreshold(channel) + s_msd.servo_cycle, 0); } // Do this last as it then turns on the timer timerSetPrescaler(timer,prescale); }else{ // We need a 16 bit bit timer setError(SERVO_TIMER_MUST_BE_16_BIT); }}
static void __servoGMService(const TimerCompare *timer_compare, void* data){ uint16_t delay; // The next delay in cycles delay = s_msd.servo_cycle; // Re-fire the timer.... // BUGBUG:: should maybe do something depending on if we have something to do or not... IE don't need to interrupt every // n mS if there are no active group moves... compareSetThreshold(timer_compare,delay + compareGetThreshold(timer_compare));}
P.S. - I hope you don't mind that I am experimenting around like this . I am enjoying getting back to the AVR and it is fun using your library.
... CRITICAL_SECTION_START; // Update the list of which servos have group move data. Do this under critical section to make sure it keeps consistent. // remember the state of which servos were active before we or it in, such that we know if our main callback function is running or not. uWhichServosActiveBefore = s_msd.uWhichServosActive; s_msd.uWhichServosActive |= uNewTimedServos; CRITICAL_SECTION_END; if ((uWhichServosActiveBefore == 0) && s_msd.uWhichServosActive) { scheduleJob(&SGMCallback, 0, clockGetus(), ((TICK_COUNT)MSPERSGMCALLBACK)*1000); // Schedule up our group move - start at the next MS#ifdef DEBUG if (getError() != 0) { rprintfInit(USB_ACTIVATE); rprintf("ESGM: %d %x %x\n", getError(), uWhichServosActiveBefore, uNewTimedServos); setError(0); }#endif }
// If there is still group moves going on, we will rescheule ourself. s_cSGMCallback++; if (s_msd.uWhichServosActive) { scheduleJob(&SGMCallback, 0, lasttime, (TICK_COUNT)(MSPERSGMCALLBACK)*1000); // reschedule our self, rember to conver mS to uS.#ifdef DEBUG if (getError() != 0) { rprintfInit(USB_ACTIVATE); rprintf("ESGMCB: %d %d\n", getError(), s_cSGMCallback); setError(0); }#endif }
}else if (! __running ){ const TimerCompare* channel = timerGetCompare(g_heartbeat,CHANNEL_NUM); __scheduleUpdate(channel, null); }
A follow up from the last message:Unless I am missreading the code, I think it is a recursion problem in scheduler.c. It is hard to describe in text but I will try1. - I call scheduleJob with my job and a delay of 20mS....2. - after 20mS __scheduleUpdate is called which is attached to the timer. It removes itself from the timer by calling compareDetach. 3) __scheduleUpdate calls my function, which does some work and decides to reschedule itself 4) Since my reschedule is > 1ms it adds to queue and calls __scheduleUpdate, which again calls compare Detach... 5) This call of __scheduleUpdate completes and calls compareAttach, which is fine and exits. 6) My function exits...7) The timer interrupt initiated call to __scheduleUpdate now calls compareAttach, but we are already attached and the call errors out.Kurt