Hello, not sure wether this question is limited to the Portenta section of the forum but since I use dual cores in my code I will post this here.
So here is what I am trying to do, I communicate on the serial port with Labview from the core M7 of my Portenta and the M4 is actually supposed to do the hardwork (getting data from adc dma and timer etc). I used HSEM to communicate variables between the two cores. These variables translate the orders received by the M7 from Labview to the M4. In Labview I implemented a possibility to change the parameters without having to reset the board which calls back the setup() and let the user change the sampling frequency (myEchVal
). Here is the code :
//////////////////////////////////CORE_CM4////////////////////////////////////
#ifdef CORE_CM4
#define HSEM_ID_INIT 0
#define HSEM_PROCESS_INIT 0
#define HSEM_ID_DATA 1
#define HSEM_PROCESS_DATA 1
#define HSEM_ID_RDY 2
#define HSEM_PROCESS_RDY 2
#define HSEM_ID_RST 3
#define HSEM_PROCESS_RST 3
#define HSEM_ID_FRQ 4
#define HSEM_PROCESS_FRQ 4
void setupLabviewM4();
int myValEch=200;
int readyP=0;
int initt=0;
int freq=0;
struct shared_data
{
uint8_t datInit;
uint8_t datFreq;
uint8_t datReset;
uint8_t datReady;
//uint32_t val;//status : 1=transfer complete 0=waiting
uint32_t data_M4toM7[3];
};
volatile struct shared_data * const buff = (struct shared_data *)0x38001000;
void setup() {
// put your setup code here, to run once:
setupLabviewM4();
}
void loop() {
while (HAL_HSEM_Take(HSEM_ID_RST, HSEM_PROCESS_RST) != HAL_OK) {};
if (buff->datReset == 1){
HAL_HSEM_Release(HSEM_ID_RST, HSEM_PROCESS_RST);
setupLabviewM4();
}else{
HAL_HSEM_Release(HSEM_ID_RST, HSEM_PROCESS_RST);
}
// put your main code here, to run repeatedly:
while (HAL_HSEM_Take(HSEM_ID_DATA, HSEM_PROCESS_DATA) != HAL_OK) {};
buff->data_M4toM7[0]=random(300);
buff->data_M4toM7[1]=random(300);
buff->data_M4toM7[2]=myValEch;
delay(myValEch);
HAL_HSEM_Release(HSEM_ID_DATA, HSEM_PROCESS_DATA);
}
void setupLabviewM4(void) {
readyP=0;
initt=0;
freq=0;
// put your setup code here, to run once:
//Serial.begin(115200);
/***************LABVIEW COM**************/
while (initt!=1) {//Check message from Labview before starting!
while (HAL_HSEM_Take(HSEM_ID_INIT, HSEM_PROCESS_INIT) != HAL_OK) {};
if (buff->datInit == 1) {
initt = 1;
} HAL_HSEM_Release(HSEM_ID_INIT, HSEM_PROCESS_INIT);
}
//delay(1000);
while (freq!=1) {
while (HAL_HSEM_Take(HSEM_ID_FRQ, HSEM_PROCESS_FRQ) != HAL_OK) {};
switch (buff->datFreq) {
case 0:
myValEch = 100;
break;
case 1:
myValEch = 200;
break;
case 2:
myValEch = 300;
break;
case 3:
myValEch = 400;
break;
case 4:
myValEch = 500;
break;
case 5:
myValEch = 600;
break;
case 6:
myValEch = 700;
break;
case 7:
myValEch = 800;
break;
case 8:
myValEch = 900;
break;
} HAL_HSEM_Release(HSEM_ID_FRQ, HSEM_PROCESS_FRQ);
freq = 1;
}
/***********SETUP******************/
randomSeed(analogRead(0));//To replace with M4 Init code
/***********SETUP DONE*************/
while (readyP!=1) {
while (HAL_HSEM_Take(HSEM_ID_RDY, HSEM_PROCESS_RDY) != HAL_OK) {};
if (buff->datReady = 1) {
readyP = 1;
} HAL_HSEM_Release(HSEM_ID_RDY, HSEM_PROCESS_RDY);
}
}
#endif
//////////////////////////////////CORE_CM7//////////////////////////////////////
#ifdef CORE_CM7
#define HSEM_ID_INIT 0
#define HSEM_PROCESS_INIT 0
#define HSEM_ID_DATA 1
#define HSEM_PROCESS_DATA 1
#define HSEM_ID_RDY 2
#define HSEM_PROCESS_RDY 2
#define HSEM_ID_RST 3
#define HSEM_PROCESS_RST 3
#define HSEM_ID_FRQ 4
#define HSEM_PROCESS_FRQ 4
int readyP=0;
int initt=0;
int freq=0;
struct shared_data
{
uint8_t datInit;
uint8_t datFreq;
uint8_t datReset;
uint8_t datReady;
//uint32_t val;//status : 1=transfer complete 0=waiting
uint32_t data_M4toM7[3];
};
volatile struct shared_data * const buff = (struct shared_data *)0x38001000;
void setupLabviewM7();
String chaineF;
void setup() {
Serial.begin(115200);
LL_RCC_ForceCM4Boot();
setupLabviewM7();
}
void loop() {
if (Serial.available() > 0) {
char incomingByte = Serial.read();
if (incomingByte == 'z') {
while (HAL_HSEM_Take(HSEM_ID_RST, HSEM_PROCESS_RST) != HAL_OK) {};
SCB_CleanInvalidateDCache_by_Addr(buff, sizeof(*buff));
buff->datInit = 0;
buff->datReset = 0;
buff->datReady = 0;
SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_RST, HSEM_PROCESS_RST);
Serial.println("reseting");
setupLabviewM7();
while (HAL_HSEM_Take(HSEM_ID_RST, HSEM_PROCESS_RST) != HAL_OK) {};
buff->datReset = 0;
SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_RST, HSEM_PROCESS_RST);
}
}
while (HAL_HSEM_Take(HSEM_ID_DATA, HSEM_PROCESS_DATA) != HAL_OK) {};
SCB_CleanInvalidateDCache_by_Addr(buff, sizeof(*buff));
chaineF = (String)buff->data_M4toM7[0] + "|" + (String)buff->data_M4toM7[1] + "|" + (String)buff->data_M4toM7[2];
//delay(100);
SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_DATA, HSEM_PROCESS_DATA);
Serial.println(chaineF);
}
void setupLabviewM7(void) {
readyP=0;
initt=0;
freq=0;
// put your setup code here, to run once:
//Serial.begin(115200);
/***************LABVIEW COM**************/
while (initt!=1) {//Check message from Labview before starting!
if (Serial.available() > 0) {
char incomingByte = Serial.read();
if (incomingByte == 'i') {
initt = 1;
while (HAL_HSEM_Take(HSEM_ID_INIT, HSEM_PROCESS_INIT) != HAL_OK) {};
SCB_CleanInvalidateDCache_by_Addr(buff, sizeof(*buff));
buff->datInit=1;
SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_INIT, HSEM_PROCESS_INIT);
}
}
}
while (freq!=1) {
if (Serial.available() > 0) {
char incomingByte = Serial.read();
while (HAL_HSEM_Take(HSEM_ID_FRQ, HSEM_PROCESS_FRQ) != HAL_OK) {};
SCB_CleanInvalidateDCache_by_Addr(buff, sizeof(*buff));
switch (incomingByte) {
case 'a':
buff->datFreq = 0;
break;
case 'b':
buff->datFreq = 1;
break;
case 'c':
buff->datFreq = 2;
break;
case 'd':
buff->datFreq = 3;
break;
case 'e':
buff->datFreq = 4;
break;
case 'f':
buff->datFreq = 5;
break;
case 'g':
buff->datFreq = 6;
break;
case 'h':
buff->datFreq = 7;
break;
case 'i':
buff->datFreq = 8;
break;
} SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_FRQ, HSEM_PROCESS_FRQ);
freq = 1;
}
}
/***********SETUP******************/
//No setup on M7
/***********SETUP DONE*************/
while (readyP!=1) {
Serial.println("ready");
if (Serial.available() > 0) {
char incomingByte = Serial.read();
if (incomingByte == 'r') {
readyP = 1;
while (HAL_HSEM_Take(HSEM_ID_RDY, HSEM_PROCESS_RDY) != HAL_OK) {};
SCB_CleanInvalidateDCache_by_Addr(buff, sizeof(*buff));
buff->datReady = 1;
SCB_CleanDCache_by_Addr(buff, sizeof(*buff));
HAL_HSEM_Release(HSEM_ID_RDY, HSEM_PROCESS_RDY);
}
}
}
}
#endif
So everything works fine except for the switch case in M4 code I checked and the value of buff->datFreq changes (correctly) when Labview calls for a change of the parameters however the value of myEchVal will keep being the same unless I reset the board and restart my Vi (kind of Labview sketch). The issue does not come from Labview since it works extremely fine when tried only on M7. It is also not linked to the M4 taking the freq semaphore first after the first init phase since putting delay did not change the end result. I am pretty sure it is a dumb mistake but I am kind of stuck with it.
I didn't put the Labview Vi here because I don't think it is linked to the issue at hand but if you think it might help I am ready to share.
EDIT : indeed it was dumb... forgot to tell M4 to reset from M7.