Pages: 1 [2] 3   Go Down
Author Topic: Nil RTOS update - Fast and Tiny!  (Read 13851 times)
0 Members and 1 Guest are viewing this topic.
Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Now the NilTimeNow() and millis() are identical (I've changed the systime to uint32_t):
Quote
382938 382933
563120 563115
808810 808806
1160186 1160182
1770719 1770715
10808014 10808011

Q: what will happen when the compare value drifts closer to 255/0 (OVF isr for millis) because of "OCR0A += 250;" ?
« Last Edit: August 17, 2013, 01:38:13 pm by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Q: what will happen when the compare value drifts closer to 255/0 (OVF isr for millis) because of "OCR0A += 250;" ?

The timer counter, TCNT0, just increments and the overflow ISR doesn't change anything.  So the compare ISR is not affected by the overflow ISR.

Adding 250 really just subtracts 6 counts or 24 microseconds until the next compare match.  As long as interrupt are not disabled for around a millisecond this will be reliable.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So when compare value will be 0, the ovf and compare isr fire simultaneously, I think. Will be both isrs processed properly then?
Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So when compare value will be 0, the ovf and compare isr fire simultaneously, I think. Will be both isrs processed properly then?

It will work correctly but there will be a little jitter in the time.  Interrupt priority on AVR is by vector location.
Quote
The interrupts have priority in accordance with their Interrupt Vector position. The lower the Interrupt Vector address, the higher the priority.
The TIMER0 COMPA interrupt is higher priority than TIMER0 OVF so the Nil systick should be processed first if both occur on the same CPU cycle.

Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have several tasks, two of them handle I2C. First reads ads1110 ADC (per. every 100ms) and the second one reads an external RTC (for example each second). Running both tasks accessing single I2C bus does not work well - it comes to data corruption.
What is the proper handling of such situation under NilRtos?
« Last Edit: August 20, 2013, 10:05:18 am by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could share the I2C bus by using a semaphore. Each thread that uses the I2C bus has this form.

Code:
// Declare and initialize a semaphore for limiting access to a region.
SEMAPHORE_DECL(i2cSem, 1);

// Time between acceses.
const systime_t PERIOD_ONE_TICKS = 123;  // set value for your case!
//------------------------------------------------------------------------------
// Declare the thread function.
NIL_THREAD(thdFcn, arg) {
  // Time for next read.
  systime_t wakeTime = nilTimeNow();
 
  while (true) {
    wakeTime += PERIOD_ONE_TICKS;

    // Sleep until time for next bus access.
    nilThdSleepUntil(wakeTime);
   
    // Wait for access to I2C bus.
    nilSemWait(&i2cSem);

    // Access I2C bus here.
   
    // Release I2C bus.
    nilSemSignal(&i2cSem);
  }
}

Another option is to access one of the devices with software I2C.

See: DigitalIO20130221.zip  - Fast digital I/O, software I2C, and software SPI http://code.google.com/p/rtoslibs/downloads/list.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok, so something like handshaking:  
Code:
// Wait for access to I2C bus.
    nilSemWait(&i2cSem);                     <<  waits on signal I2C is free (resource semaphore 1 -> 0 )
    // Access I2C bus here.    
    // Release I2C bus.
    nilSemSignal(&i2cSem);                   >>  signals I2C is free (resource semaphore 0 -> 1 )
I'll try..
thx..it seems it works.. now I know why we need counting semaphores smiley
« Last Edit: August 20, 2013, 03:26:56 pm by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It might be nice if Nil had a Mutex which is intended for mutual exclusion.  Here is an excellent little article http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:semaphores_mutexes.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Could be the setsyncProvider() with setSyncInterval() used in setup() with Nirtos? Or better, a task shall be used for syncing (instead of the setSyncInterval())?
Code:
   setSyncProvider(RTC.get);   // the function to get the time from the actual RTC
..
     setSyncInterval(300);         // set the number of seconds between re-sync of time
     nilSysBegin();
« Last Edit: August 21, 2013, 04:55:13 pm by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What are setSyncProvider() and setSyncInterval()?  They are not in the posted version of NilRTOS.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It comes from Time.h
PS:  setSyncProvider() calls RTC in regular intervals in order to sync "local time" (based on millis(). So it seems it must be guarded by a mutex.
« Last Edit: August 22, 2013, 05:56:02 am by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You just need to define a protected function to return the time.  All access to I2C must be protected by the same semaphore.

Code:
time_t safeGetTime() {
  time_t t;
  nilSemWait(&i2cSem);   
  t = RTC.get();
  nilSemSignal(&i2cSem);
  return t;
}

  ...

  setSyncProvider(safeGetTime);   // the function to get the time from the actual RTC
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I did it with a periodic task. Yours is more resource friendly, of course smiley
Code:
while (TRUE) {

wakeTime += SYSTIME_SYNC_PERIOD_TICKS;

// Sleep until time for next data point
nilThdSleepUntil(wakeTime);

// Read RTC..
nilSemWait(&i2cfree);
new_time = rtc.get_tm();
nilSemSignal(&i2cfree);
// .. and sync system Time and Date
setTime(new_time);
now();  // this makes the sync
}
}

Q: can I work with semaphores before I start the NilRtos? Like:

Code:
..
// SYNC the RTC and systime at boot
setSyncProvider(safeGetTime);   // the function to get the time from RTC
if(timeStatus()!= timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");  
setSyncInterval(300); // set the number of seconds between re-sync of time
sys_t_start = now(); // keep the boot start time
..
nilSysBegin();

While running above I get a proper time into "sys_t_start" var - it means the setSyncProvider() has called the safeGetTime() already.. So it had worked with semaphores, before the NilRtos actually started..


« Last Edit: August 22, 2013, 12:16:03 pm by pito » Logged

0
Offline Offline
Edison Member
*
Karma: 63
Posts: 1598
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You will get away with calling safeGetTime before starting Nil since there will be no wait on the semaphore.  nilSemWait will decrement the count to zero and return.

It won't work if you need to wait.
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2061
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've installed SdFat's demos (Bench and SdInfo) into my Nil experimental setup. The issue is they use SdFat and Sd2Card respectively. So to put them together work with
Code:
SdFat sd;
Sd2Card card;
only, I was not able to merge the stuff such it uses only one class for the card. And it works smiley-eek (very surprised though) under Nil even under "heavy" load (several periodic tasks run in bg)  smiley-wink.
Code:
PITO> sdinfo
SDINFO

SdFat version: 20130710

init time: 15 ms

Card type: SDHC

Manufacturer ID: 0X3
OEM ID: SD
Product: SU04G
Version: 8.0
Serial number: 35763829101
Manufacturing date: 11/2012

cardSize: 3965.19 MB (MB = 1,000,000 bytes)
flashEraseSize: 128 blocks
eraseSingleBlock: true

SD Partition Table
part,boot,type,start,length
1,0X0,0XB,8192,7733248
2,0X0,0X0,0,0
3,0X0,0X0,0,0
4,0X0,0X0,0,0

Volume is FAT32
blocksPerCluster: 64
clusterCount: 120704
freeClusters: 112067
freeSpace: 3672.21 MB (MB = 1,000,000 bytes)
fatStartBlock: 14496
fatCount: 2
blocksPerFat: 944
rootDirStart: 2
dataStartBlock: 16384

PITO> sdbench
SDBENCH
Free RAM: -1203
Type is FAT32
File size 5MB
Buffer size 1024 bytes
Starting write test.  Please wait up to a minute
Write 140.21 KB/sec
Maximum latency: 442936 usec, Minimum Latency: 3252 usec, Avg Latency: 7294 usec

Starting read test.  Please wait up to a minute
Read 400.25 KB/sec
Maximum latency: 5784 usec, Minimum Latency: 2196 usec, Avg Latency: 2551 usec

Done

PITO> stack
STACK
Stack Sizes: 197 85 85 101 101 85 117 85 117 197 85 197 165 197 197 309 309 10107
Unused Stack: 165 55 55 47 49 55 87 55 87 58 55 167 41 71 167 192 50 9995
PITO>

BTW the FreeRam() does not work under Nil well.
« Last Edit: August 24, 2013, 11:36:17 am by pito » Logged

Pages: 1 [2] 3   Go Up
Jump to: