What I have made is an interface function that exports a pointer to the client, and the client later on uses that pointer to ask for the data through a non-interface function. This probably "is undefined behavior for an unsafe pointer to be written from one task and read from another." (XMOS Programming Guide).
The code below still seems to work when I test it alone, but when I compile and run the same type of code (with the tasks doing all the other jobs as well) in a larger system on an xCORE-200 eXplorerKIT then byte 0 is passed over correctly always, but the other bytes are rubbish. However, I did had a row of compilations when all bytes came over correctly, but I lost that track. In other words, the code below really cannot be correct, can it?
Any ideas?
Code: Select all
// Error messages updated in http://www.teigfam.net/oyvind/home/technology/141-xc-is-c-plus-x/
// xTIMEcomposer 14.3.3
#include <platform.h>
#include <stdio.h>
#include <stdint.h> // uint8_t
#include <timer.h> // XS1_TIMER_HZ etc
#include <iso646.h> // not, and etc.
typedef signed int time32_t;
typedef interface radio_if_t {
// unsigned * get_radio_log_value_ptr (void); // error: pointer return type must be marked movable, alias or unsafe (contradicts the below)
// unsigned * alias get_radio_log_value_ptr (void); // error: alias pointer return type for interface functions are not supported (contradicts the above)
// unsigned * movable get_radio_log_value_ptr (void); // RFM69_driver needs to own this at all times I would think
unsigned * unsafe get_radio_log_value_ptr (void);
} radio_if_t;
unsigned get_radio_log_value (unsigned * unsafe radio_log_value_ptr) {
unsigned return_radio_log_value;
unsafe {
return_radio_log_value = *radio_log_value_ptr;
// As this simple built it works, see log below
// On a much more complex build than this, on the xCORE-200 eXplorerKIT, only byte 0 came over correctly, the other three bytes were rubbish, however
// there were builds where even those builds seemed to work
}
return return_radio_log_value;
}
void RFM69_driver (
server radio_if_t i_radio) {
timer tmr;
time32_t time;
unsigned radio_log_value = 0x65432100;
unsigned * radio_log_value_ptr = &radio_log_value; // unsafe here does not help
tmr :> time;
time += XS1_TIMER_HZ;
while (1) {
select {
case i_radio.get_radio_log_value_ptr (void) -> unsigned * unsafe radio_log_value_ptr_ : {
unsafe {
radio_log_value_ptr_ = radio_log_value_ptr;
}
printf ("DELIVERED address %08X\n", radio_log_value_ptr_);
} break;
case tmr when timerafter(time) :> void : {
time += XS1_TIMER_HZ;
radio_log_value++;
printf ("NOW %08X\n", radio_log_value);
} break;
}
}
}
void RFM69_client (
client radio_if_t i_radio) {
timer tmr;
time32_t time;
unsigned radio_log_value;
unsigned * unsafe radio_log_value_ptr;
tmr :> time;
time += (2 * XS1_TIMER_HZ);
radio_log_value_ptr = i_radio.get_radio_log_value_ptr();
while (1) {
select {
case tmr when timerafter(time) :> void: {
time += (2 * XS1_TIMER_HZ);
radio_log_value = get_radio_log_value(radio_log_value_ptr);
printf ("GOT %08X\n", radio_log_value);
} break;
}
}
}
int main(void) {
interface radio_if_t i_radio;
par {
RFM69_driver (i_radio);
RFM69_client (i_radio);
}
return 0;
}
Code: Select all
DELIVERED address 0007FD2C
NOW 65432101
GOT 65432101
NOW 65432102
NOW 65432103
GOT 65432103
NOW 65432104
NOW 65432105
GOT 65432105
NOW 65432106
NOW 65432107
GOT 65432107
NOW 65432108
NOW 65432109
GOT 65432109
NOW 6543210A