Hi,
I am not an expert here but I did see something that could be the cause of your
problem.
I think the problem might be in the way in which you are starting the two different
threads. I have cut some stuff out so as to show what I am talking about.
> 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);
In this piece of code you are using attr to hold the attributes of the thread. That
is fine. However, below...
> 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);
you are using the same attr variable for the second thread. I am not an expert but I
believe that since the calls to the pthread routines require &attr that they are
modifying its values. This could include the address of the thread to get executed.
Since you created the thread for the adc first it executes once. Then you create the
thread for the servo loop and it modifies the attr structure to look at the servo loop
and it continues to run.
As a quick test use another attribute structure like attr1 to create a separate thread
attribute structure for one of the threads.
Hope this helps, and hope it doesn't hurt.
Rich
-----Original Message-----
From: Ken Ramey [mailto:[EMAIL PROTECTED]]
Sent: Monday, June 25, 2001 10:05 AM
To: [EMAIL PROTECTED]
Subject: [rtl] Problem with multiple threads
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/
----- 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/