Re: Porting the Arduino millis(), possible?
Posted: Thu Mar 22, 2018 11:29 am
Good question, since yours compiled!
Here I have the problem. I have four files, really, but I mimicked the structure here. I have moved millis_state_t my_millis = {0,0}; from inside one of the tasks to above main.
In my head your code should have caused the same violation.. Because the violation is correctly reported (in my head).
Here is the error log (line numbering don't match, I use a long file with #ifdefs for all kinds of code testing):
I like this. We're onto something, aren't we?
Update: It's the same task that's instantiated twice. And when it contains the global instatiation it incorrectly (?) does not report the violation?
Here I have the problem. I have four files, really, but I mimicked the structure here. I have moved millis_state_t my_millis = {0,0}; from inside one of the tasks to above main.
In my head your code should have caused the same violation.. Because the violation is correctly reported (in my head).
Code: Select all
// See http://www.xcore.com/viewtopic.php?f=26&t=6470&start=10
#include <stdio.h>
#include <xs1.h>
#include <iso646.h>
#include <timer.h> // delay_milliseconds(200), XS1_TIMER_HZ etc
typedef enum {false,true} bool;
#define DEBUG_PRINT_TEST 1
#define debug_print(fmt, ...) do { if(DEBUG_PRINT_TEST) printf(fmt, __VA_ARGS__); } while (0)
// ---- Would be in a header file ----
typedef struct millis_state_t {
unsigned long tick_hi;
unsigned long last_tick;
} millis_state_t;
millis_state_t millis_state; // "extern" or not makes no difference here, but I do need it in the header file
#define MILLIS() millis_p(millis_state)
// ---- Would be in a source file ----
unsigned long millis_p (millis_state_t &millis_state) {
timer tmr;
unsigned long long total_ticks;
unsigned long current_tick;
tmr :> current_tick;
if( current_tick < millis_state.last_tick ) {
++millis_state.tick_hi;
}
millis_state.last_tick = current_tick;
total_ticks = ((unsigned long long)millis_state.tick_hi << 32) | (unsigned long long)current_tick;
return (unsigned long)(total_ticks / (unsigned long long)XS1_TIMER_KHZ);
}
// ---- I actually have two files for two different tasks ----
unsigned digitalRead (void) {
delay_milliseconds (200);
return (0);
}
#define RF69_TX_LIMIT_MS 1000
#define TEST_TYPE unsigned long
void test_task (int task_num) {
TEST_TYPE millis_;
TEST_TYPE txStart;
unsigned testCnt = 0;
bool not_timed_out;
while (testCnt < 2000) {
txStart = MILLIS();
do {
millis_ = MILLIS();
not_timed_out = (millis_ - txStart) < RF69_TX_LIMIT_MS;
debug_print ("task %d: testCnt(%d), millis(%d), txStart(%d), millis_-txStart(%d), timedOut(%d)\n",
task_num, testCnt, millis_, txStart, millis_ - txStart, !not_timed_out);
delay_milliseconds(20);
} while ((digitalRead() == 0) && not_timed_out);
testCnt++;
}
}
// ---- In main.xc ----
millis_state_t my_millis = {0,0};
int main() {
par { // error: use of `millis_state' violates parallel usage rules
test_task(0);
test_task(1);
}
return 0;
}
Code: Select all
11:20:33 **** Incremental Build of configuration Default for project _xmos_issues ****
xmake CONFIG=Default all
Checking build modules
No build modules used.
Analyzing main.xc
Creating dependencies for main.xc
Compiling main.xc
Creating xmos_issues_nnnm.xe
../src/main.xc:1701:9: error: use of `millis_state' violates parallel usage rules
par { // error: use of `millis_state' violates parallel usage rules
^~~
../src/main.xc:1684:23: note: object used here
txStart = MILLIS();
^~~~~~~~
../src/main.xc:1649:31: note: expanded from here
#define MILLIS() millis_p(millis_state)
^~~~~~~~~~~~
../src/main.xc:1684:23: note: object used here
txStart = MILLIS();
^~~~~~~~
../src/main.xc:1649:31: note: expanded from here
#define MILLIS() millis_p(millis_state)
^~~~~~~~~~~~
xmake[1]: *** [bin//xmos_issues_nnnm.xe] Error 1
xmake: *** [bin//xmos_issues_nnnm.xe] Error 2
11:20:34 Build Finished (took 863ms)
Update: It's the same task that's instantiated twice. And when it contains the global instatiation it incorrectly (?) does not report the violation?