In embedded systems, limited hardware resources are to be expected. The previously suggested approaches would utilize the hardware inefficiently by using wait, causing high CPU load during the remaining time, which could result in insufficient processing time. This could lead to missed sampling times or significant fluctuations.
The following problems or drawbacks should be avoided:
1. The sampling accuracy heavily depends on the precision of the wait(1) call. When 100 channels are checked afterward, each with potentially different sampling periods and hardware accesses, the operations are not deterministic, and the overall timing may fall out of sync. The allowed timing deviations were not specified, but they would be difficult to predict and control.
2. A significant amount of time is wasted during the waiting period, where other tasks could be executed instead.
3. Periods that are not divisible by 1000 would be skipped when the cycle resets to 1, leading to potential sampling errors.
In a typical embedded system, only a limited number of hardware timers are available, so assigning a dedicated hardware timer to each of the 100 channels is not practical. It is necessary to multiplex tasks, while the system should remain flexible enough to support different sampling periods for each channel. At the same time, the CPU should be utilized optimally, minimizing CPU load.
No information is provided on the required or achievable sampling accuracy, and this would need to be defined and verified to ensure that the system is capable of meeting these requirements. While some deviations in sampling intervals may be acceptable for typical embedded applications, it’s important to assess this upfront.
One option is to use a timer interrupt as the clock base for managing multiple channels with different sampling intervals, instead of wasting time with wait. A hardware timer with the smallest required interval (e.g., 1 ms) could increment a counter within the timer ISR. This counter would then serve as a base for determining the different sampling intervals of the 100 channels. Each channel’s last sample time would be tracked, allowing the system to decide if a channel should be sampled again based on the timer value and the configured sampling period.
A concept with a central timer and multiple channels could be structured roughly as follows:
volatile unsigned long timerCount = 0;
void Timer_ISR()
{
timerCount++; }
void main_loop()
{
const int numChannels = 100;
int channelLastSample[numChannels];
while (1) {
unsigned long currentTimerCount = timerCount;
for (int i = 0; i < numChannels; ++i) {
int samplePeriod = DataCh[i].SamplePeriod;
if (currentTimerCount - channelLastSample[i] >= samplePeriod) {
ReadDataCh(i); channelLastSample[i] = currentTimerCount; }
}
}
}
Since race conditions could occur within an ISR, additional measures like atomic operations or temporarily disabling interrupts might be necessary.