I have been beating my head against this problem for over a week now and thought
I'd solicit some help from this group. I have a system with the following two
functions, each of which needs to run as a seperate thread in RTLinux. adcThread
is supposed to run at a rate of 100Hz and monitor the forces on a set of load
cells. servo_thread runs at 50Hz and compares the currently recorded load cell
readings with the target readings and implements a PI servo loop to control the
forces. The printk() statements were put in for debugging purposes to show what is
happening in the system.
Here are the symptoms I am seeing:
* Both threads appear to be successfully created, marked for periodic execution,
and started.
* servo_thread runs at 100Hz, as expected, until removed from the system with
rmmod.
* adcThread runs _one_ time, going to sleep and never again being awakened.
I have tried various re-arrangements of the code; putting servoTask ahead of
adcTask, decreasing the frequency of each and of both tasks, and having adcTask be
the _only_ task in the system. In each case, the behavior is the same.
I apologize for the length of this note, but I couldn't think of any other way to
illustrate what is happening besides including the code in question. Any
help/ideas/suggestions that anyone can provide would be greatly appreciated and
publically acknowledged. :-)
Thanks.
Ken Ramey
void *adcThread(void *t)
{
unsigned short int adc_chan;
unsigned short int csr_temp, ctrl_reg;
int sampleCnt;
int adc_counts[ADC_CHANS];
while (TRUE)
{
printk(KERN_INFO "adcThread active\n");
csr_temp = IOSPACEW(adc_slot,ADC_CSR) & 0xe3f0;
for (adc_chan = 0; adc_chan < ADC_CHANS; adc_chan++)
adc_counts[adc_chan] = 0;
sampleCnt = 0;
while (sampleCnt < SAMPLE_SIZE)
{
for (adc_chan = 1; adc_chan <= ADC_CHANS; adc_chan++)
{
ctrl_reg = csr_temp | ((adc_chan - 1) >> 1);
if ((adc_chan % 2) == 0)
ctrl_reg |= 0x10;
else
ctrl_reg |= 0x08;
IOSPACEW(adc_slot,ADC_CSR) = ctrl_reg;
usleep(5);
IOSPACEW(adc_slot,ADC_CONVERT) = 0xffff;
usleep(11);
adc_counts[adc_chan - 1] += IOSPACEW(adc_slot,ADC_DATA);
}
sampleCnt++;
}
for (adc_chan = 0; adc_chan < ADC_CHANS; adc_chan++)
curCounts[adc_chan] = adc_counts[adc_chan] / SAMPLE_SIZE;
IOSPACEW(adc_slot,ADC_CSR) = csr_temp;
printk(KERN_INFO "adcThread going to sleep\n");
pthread_wait_np();
}
printk(KERN_IN FO "adcThread exiting\n");
}
void *servo_thread(void *t)
{
int error;
int ival;
int dacout[AXIS];
int i;
int rawCount = 0;
int errSum[AXIS] = {0, 0};
while (TRUE)
{
printk(KERN_INFO "servo_thread active\n");
for (i = 0; i < AXIS; i++)
{
rawCount = curCounts[6 + i]; /* raw value from the adc */
error = targetCount[i] - rawCount;
ival = errSum[i] + 0.015 * error;
if (ival > DAC_MID + 1000) /* +1000 from midpoint of DAC */
ival = DAC_MID + 1000;
if (ival < DAC_MID - 1000) /* -1000 from midpoint of DAC */
ival = DAC_MID - 1000;
dacout[i] = (1 * error + errSum[i]);
errSum[i] = ival;
if (dacout[i] < 0)
dacout[i] = 0;
else if (dacout[i] > 65535)
dacout[i] = 65535;
IOSPACEW(dac_slot,i * 2) = (unsigned short) dacout[i];
}
/* Sleep until our next interval occurs */
printk(KERN_INFO "servo_thread sleeping\n");
pthread_wait_np();
}
}
The two threads are started with the following code:
...
pthread_attr_init(&attr);
sched_param.sched_priority = 90;
pthread_attr_setschedparam(&attr, &sched_param);
retVal = pthread_create(&adcTask, &attr, adcThread, (void *)1);
if (retVal != 0)
printk(KERN_INFO "Unable to create ADC Thread. RC = %d\n", retVal);
retVal = pthread_make_periodic_np(adcTask, gethrtime() , 10000000);
if (retVal != 0)
printk(KERN_INFO "Unable to start adcThread\n");
sched_param.sched_priority = 100;
pthread_attr_setschedparam(&attr, &sched_param);
retVal = pthread_create(&servoTask, &attr, servo_thread, (void *)1);
if (retVal != 0)
printk(KERN_INFO "Unable to create Servo Thread. RC = %d\n", retVal);
pthread_attr_setfp_np(servoTask, 1);
retVal = pthread_make_periodic_np(servoTask, gethrtime() , 20000000);
if (retVal != 0)
printk(KERN_INFO "Unable to start servoTask\n");
...
----- End of forwarded message from [EMAIL PROTECTED] -----
-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
--
For more information on Real-Time Linux see:
http://www.rtlinux.org/