Yes, there is a race condition. But I guess since the variable "g_last_tick" is only used to check for overflow of the timer -- to extend the resolution -- it's going to be in the resolution extension where any errors will be observed, so really it's every 43 seconds you could get some errors I suppose, assuming you call the function with some regularity. Honestly the shared globals don't really save anything, just a few bytes of RAM, so I don't know if it's worthwhile to take the risk. It's better for each core to have its own resolution extension. Each core that calls the function will use its own hardware timer (you can see that if you compile with -report) so I don't think there's any real benefit to the shared globals.
As for the long long, I didn't even know XC wasn't supposed to support 64 bit types. Otherwise I wouldn't have tried it. I am using xTIMEcomposer 14.3.2.
Porting the Arduino millis(), possible? Topic is solved
-
- XCore Expert
- Posts: 580
- Joined: Thu Nov 26, 2015 11:47 pm
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
So a startKIT processor with one slice and 8 cores actually has 8 system timers? And the eXplorerKIT with two slices would have 16? These would be read-only, wouldn't they? Why would that be needed?akp wrote:Each core that calls the function will use its own hardware timer (you can see that if you compile with -report) so I don't think there's any real benefit to the shared globals.
akp wrote:As for the long long, I didn't even know XC wasn't supposed to support 64 bit types. Otherwise I wouldn't have tried it. I am using xTIMEcomposer 14.3.2.
Off Topic
Yes, I do use the last 14.3.2 but not on macOS High Sierra. I run it on El Capitan to have it working fluently. See http://www.teigfam.net/oyvind/home/tech ... igh_sierra. I am really awaiting a new xTIMEcomposer/Java pair. I do run it also on High Sierra on another machine, but then I need to Flash from Terminal. Please tell me it's not true any more.
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- XCore Expert
- Posts: 580
- Joined: Thu Nov 26, 2015 11:47 pm
Sorry, I run it on Win7 x64 and have run it on Ubuntu but not Mac OSX. I have instantiated 8 test_task() and this is what -report gives me. It seems my code uses 1 timer for something and then 1 per core.
Code: Select all
Creating millis.xe
Constraint check for tile[0]:
Cores available: 8, used: 8 . OKAY
Timers available: 10, used: 9 . OKAY
Chanends available: 32, used: 1 . OKAY
Memory available: 65536, used: 5936 . OKAY
(Stack: 2384, Code: 2848, Data: 704)
Constraints checks PASSED.
Build Complete
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
One timer per core matter:
TARGET = STARTKIT
I have always thought that these were not the timer counter hw but how many "timer" statements that I could have in XC?
And that that was, in some mysterious way mapped to "Timers available" (without thinking, really). Then there is 10 on the startKIT? Will it take the other 2 from the other slice that runs the debugger?, then?
TARGET = STARTKIT
Code: Select all
Constraint check for tile[0]:
Cores available: 8, used: 4 . OKAY
Timers available: 10, used: 4 . OKAY
And that that was, in some mysterious way mapped to "Timers available" (without thinking, really). Then there is 10 on the startKIT? Will it take the other 2 from the other slice that runs the debugger?, then?
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
I see in f.ex. [1] that there are
It could be one of these timers per XC timer, but then with the strong optimalisation that xcc has, it could be less.
Like, with chanends: it's not always two per chan. It depends on how a task runs and how it shares its select with another task. I tried to get an answer on that once, but failed to [2]. [3], however, did get some response. I guess that there is only one system timer per chip or.. per tile?
However I do notice that I am only allowed to have one timer in any select, indicating that you akp, must have some right here! (I haven't checked nested selects). But I have seen no restrictions on timers in [[combinable]] tasks running on the same logical core. Also, there is the setclk instruction [4] with the text "Set clock for a resource". Resource = thread or core?
Then in the [1] again I see in Figure 1 that there are "xTIME: schedulers, timers, clocks" which confuses me further. Probably XMOS hasn't been 100% concise with wording.
I would certainly like someone to tell me how this really is. Further than my speculations above. I am after timer timers, not clock blocks or port timing.
[1] "XS1-U16A-128-FB217 Datasheet" (XM002326)
[2] Calculating number of chanends
[3] Using a chanend in both directions
[4] "Assembly Programming Manual" (X9432B)
Perhaps indicating that there is not really one timer per core. But, like 10 per tile, each tile 8 cores.Hardware resources
• 12 clock blocks (6 per tile)
• 20 timers (10 per tile)
• 8 locks (4 per tile)
It could be one of these timers per XC timer, but then with the strong optimalisation that xcc has, it could be less.
Like, with chanends: it's not always two per chan. It depends on how a task runs and how it shares its select with another task. I tried to get an answer on that once, but failed to [2]. [3], however, did get some response. I guess that there is only one system timer per chip or.. per tile?
However I do notice that I am only allowed to have one timer in any select, indicating that you akp, must have some right here! (I haven't checked nested selects). But I have seen no restrictions on timers in [[combinable]] tasks running on the same logical core. Also, there is the setclk instruction [4] with the text "Set clock for a resource". Resource = thread or core?
Then in the [1] again I see in Figure 1 that there are "xTIME: schedulers, timers, clocks" which confuses me further. Probably XMOS hasn't been 100% concise with wording.
I would certainly like someone to tell me how this really is. Further than my speculations above. I am after timer timers, not clock blocks or port timing.
[1] "XS1-U16A-128-FB217 Datasheet" (XM002326)
[2] Calculating number of chanends
[3] Using a chanend in both directions
[4] "Assembly Programming Manual" (X9432B)
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- XCore Expert
- Posts: 580
- Joined: Thu Nov 26, 2015 11:47 pm
I have to admit I am not an expert myself on the ins and outs of the XMOS hardware, but I suspect you are on to something with your discovery with respect to select. I think if you try to select on 2 timeouts, you will need 2 timers -- presumably the underlying hardware for a timer is really something like a compare register that compares to the tile hardware timer? If you look in the right document you can probably find out. I can say I have some combinable code (bidirectional UART) that runs with 2 timers, one for TX and one for RX bit rate clock. I can instantiate the code combined or not combined and it works OK.
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
You are right, akp. Select/case on the same timer causes
even if a guard would only allow one of them to be selected. Like (value==1)=> in one and (value==2)=> in the other, which didn't make it any more legal.
When I added another timer in a select it's ok. It must be, thinking it over (and I have been used to it in "all" the CSP-type framework/languages I have seen).
However, I got the same
when I added the extra timer. Even if I made sure that they did individual things, so that as far as I can see the code couldn't have been optimised away. The task is [[combinable]].
Now, someone at XMOS should set things straight!?
By the way, the error text above would better have been
Code: Select all
error: timer used in more than one case
When I added another timer in a select it's ok. It must be, thinking it over (and I have been used to it in "all" the CSP-type framework/languages I have seen).
Off Topic
I've even written a paper on different type of timers for a framework we did at work (New ALT for Application Timers and Synchronisation Point Scheduling).
Code: Select all
Timers available: 10, used: 4 . OKAY
Now, someone at XMOS should set things straight!?
By the way, the error text above would better have been
Code: Select all
error: the same timer used in more than one case
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
By the way, I have posted this: XC and long long, float, double and long double
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- Respected Member
- Posts: 510
- Joined: Wed Apr 25, 2012 8:52 pm
I am testing! With the non-global solution I get "error: use of `millis_state' violates parallel usage rules" on the par in main. You say that you have a race in the global solution (that I absolutely would not want) (but that I could accept if it will never happen if I always use it more often than about 43 seconds (?), because that's the limitation of a standard timer's timerafter as well).
I could make such a system per par component (=task). I of course also get this if the two places where MILLIS() is used is placed on the same core.
I tend to start to think that the solution I have shown that works well here that's based on standard timer usage, or the 0.65536ms resolution code in this thread (and then use more ticks.. like 1526 per second) would be easier. In my real code I have wrapped the standard pattern into a function like this, with error handling and all, and I now think I will stay with it (I am working with the RFM69HCW radio board from adafruit):
I could make such a system per par component (=task). I of course also get this if the two places where MILLIS() is used is placed on the same core.
I tend to start to think that the solution I have shown that works well here that's based on standard timer usage, or the 0.65536ms resolution code in this thread (and then use more ticks.. like 1526 per second) would be easier. In my real code I have wrapped the standard pattern into a function like this, with error handling and all, and I now think I will stay with it (I am working with the RFM69HCW radio board from adafruit):
Code: Select all
// INTERNAL FUNCTION
uint8_t // readFromRegValue
while_readRegExpectedMask (
const uint8_t readFromReg, // Like REG_IRQFLAGS1
const uint8_t readFromRegMask, // Like RF_IRQFLAGS1_MODEREADY
const bool invertedLogic, // like LOGIC_NORMAL
const unsigned timeout_ms, // Like 200
const unsigned error_bit, // like ERROR_BIT_RF_IRQFLAGS1_MODEREADY
client spi_master_if i_spi, // For writeReg and readReg macros
spi_params_t &spi_params, // --"--
rfm69_internals_t &radio)
{
timer tmr;
time32_t now_time_ticks;
time32_t start_time_ticks;
time32_t timeout_at_ticks;
bool timed_out;
uint8_t readFromRegValue;
bool return_read_ok;
debug_print ("%s","loop?\n");
tmr :> start_time_ticks;
timeout_at_ticks = start_time_ticks + (timeout_ms * XS1_TIMER_KHZ);
do {
readFromRegValue = readReg (readFromReg); // readReg
return_read_ok = ((readFromRegValue bitand readFromRegMask) != 0) xor invertedLogic;
if (not return_read_ok) {
tmr :> now_time_ticks;
timed_out = AFTER_32 (now_time_ticks, timeout_at_ticks);
if (not timed_out) {
// Do another round
} else {
radio.error_bits or_eq (1<<error_bit);
debug_print ("%s","timeout!\n");
}
} else {} // Finished
} while ((not return_read_ok) and (not timed_out));
return readFromRegValue; // Plus radio.error_bits
}
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
-
- XCore Expert
- Posts: 580
- Joined: Thu Nov 26, 2015 11:47 pm
What is the minimal code that causes the parallel usage rules error? I seem to be able to use it ok.