Hello, I developed an emmbedded application for a C167CR-LM. In this application I've some very big data structures stored in internal RAM (IDATA) and some dynamic list managed using malloc and free. For dynamic allocation I define the pool:
unsigned char far equivalence_pool[0x4000]; init_mempool (equivalence_pool, sizeof (equivalence_pool));
In my application there is a IRQ routine on a Timer T6 with a period of 0.5 ms.
In some situations the ILLOPA exception is trapped an the application crashes. It generally happens when many digital input (linked to port P2 pins) are active together.
I tried to increase the user stack with no effect.
Adding 2 calls to printf in the IRQ routine, ILLOPA is not generated.
Have you some suggestions for help me how to investigate this problem?
Testing with Mon166 the trap routines are not available, and using Simulator is too complex cause the hardware and input sequences to generate.
Thanks, Marco
Here the 2/4 part of the code:
... // Ritardi e campionamenti a spazio countEnc = ENCPORT[0]; for (i = 0; i < MTL_BUFNUM; i++) { // Contatore trigger di attivazione if (MetalCounter[i].StartCount != NO_COUNT) { gapEnc = abs(countEnc - MetalCounter[i].EncPrev); if (gapEnc > MAX_GAP) { // l'encoder e' passato per lo zero // Calcolo il decremento interpretando la direzione di // conteggio dell'encoder MetalCounter[i].StartCount -= (countEnc > MAX_GAP) ? (0xFF - countEnc + MetalCounter[i].EncPrev) : (0xFF + countEnc - MetalCounter[i].EncPrev); } else MetalCounter[i].StartCount -= gapEnc; if (MetalCounter[i].StartCount <= 0) { // printf("\nFine StartCount su buffer %d\n",i); MetalCounter[i].ReadEnable = 1; MetalCounter[i].Active = 1; MetalCounter[i].Broken = 0; MetalCounter[i].StartCount = NO_COUNT; ErrReset = ResetBuf(i); // Resetto il buffer i } } // Contatore trigger di disattivazione if (MetalCounter[i].StopCount != NO_COUNT) { gapEnc = abs(countEnc - MetalCounter[i].EncPrev); if (gapEnc > MAX_GAP) { // l'encoder e' passato per lo zero // Calcolo il decremento interpretando la direzione di // conteggio dell'encoder MetalCounter[i].StopCount -= (countEnc > MAX_GAP) ? (0xFF - countEnc + MetalCounter[i].EncPrev) : (0xFF + countEnc - MetalCounter[i].EncPrev); } else MetalCounter[i].StopCount -= gapEnc; if (MetalCounter[i].StopCount <= 0) { // printf("\nFine StopCount su buffer %d\n",i); MetalCounter[i].EndDoc = MetalDetection.SensorsDelay; MetalCounter[i].StopCount = NO_COUNT; } } // Contatore timer di campionamento if (MetalCounter[i].Timer != NO_COUNT) { gapEnc = abs(countEnc - MetalCounter[i].EncPrev); if (gapEnc > MAX_GAP) { // l'encoder e' passato per lo zero // Calcolo il decremento interpretando la direzione di // conteggio dell'encoder MetalCounter[i].Timer -= (countEnc > MAX_GAP) ? (0xFF - countEnc + MetalCounter[i].EncPrev) : (0xFF + countEnc - MetalCounter[i].EncPrev); } else MetalCounter[i].Timer -= gapEnc; if (MetalCounter[i].Timer <= 0) { // printf("\nFine Timer su buffer %d\n",i); MetalCounter[i].ReadEnable = 1; MetalCounter[i].Timer = NO_COUNT; } } // Contatore bit di dato valido if (MetalCounter[i].CountValid != NO_COUNT) { gapEnc = abs(countEnc - MetalCounter[i].EncPrev); if (gapEnc > MAX_GAP) { // l'encoder e' passato per lo zero // Calcolo il decremento interpretando la direzione di // conteggio dell'encoder MetalCounter[i].CountValid -= (countEnc > MAX_GAP) ? (0xFF - countEnc + MetalCounter[i].EncPrev) : (0xFF + countEnc - MetalCounter[i].EncPrev); } else MetalCounter[i].CountValid -= gapEnc; if (MetalCounter[i].CountValid <= 0) { // printf("\nFine CountValid su buffer %d\n",i); MetalCounter[i].Valid = 0; MetalCounter[i].CountValid = NO_COUNT; // Abilitazione invio report LENTO1 MetalDetection.SendRepEnable = 1; } } // La lettura attuale diventa lettura precedente // per il prossimo interrupt da Timer6 MetalCounter[i].EncPrev = countEnc; } // for (i = 0; i < MTL_BUFNUM; i++) - Spazio } // Fine Sezione 1 - Ritardi e abilitazioni //to be continued
Here the 3/4 part of the code:
// ************************* LETTURA SENSORI ************************* // le nuove versioni (VerHw = 1) hanno gli ingressi attivi alti metaldata = (Hw) ? (~P2 & MaskInSpeed) : (P2 & MaskInSpeed); // Shift per isolare solo i sensori (0 e 1 vanno all'encoder, // 2-10 vanno ai sensori, 11 va' al trigger) metaldata = metaldata >> (NInputSpeed - 9 - 1); metaldata &= 0x01FF; // Interpretazione ingressi tramite polarity metaldata ^= MetalDetection.SensorsPolarity; // ***************** SCANSIONI RICERCA METALLI ********************** // Sezione 2 - Scansione documento e matrice for (i = 0; i < MTL_BUFNUM; i++) { if (MetalCounter[i].ReadEnable) { if (MetalCounter[i].EndDoc == NO_ENDDOC) { // Salvo sulla matrice di scansione la prima barriera di sensori ScanMatrix[i][0][ScanDoc[i].TotCol] = metaldata & 0x0001; ScanMatrix[i][2][ScanDoc[i].TotCol] = (metaldata >> 2) & 0x0001; ScanMatrix[i][4][ScanDoc[i].TotCol] = (metaldata >> 4) & 0x0001; ScanMatrix[i][6][ScanDoc[i].TotCol] = (metaldata >> 6) & 0x0001; ScanMatrix[i][8][ScanDoc[i].TotCol] = (metaldata >> 8) & 0x0001; if (ScanDoc[i].TotCol >= MetalDetection.SensorsDelay) { // if (ScanDoc[i].TotCol == MetalDetection.SensorsDelay) // printf("\nStart lettura seconda barriera su buffer %d\n",i); // Salvo sulla matrice di scansione la seconda barriera di sensori ScanMatrix[i][1][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 1) & 0x0001; ScanMatrix[i][3][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 3) & 0x0001; ScanMatrix[i][5][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 5) & 0x0001; ScanMatrix[i][7][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 7) & 0x0001; // Analizzo la colonna appena completata per identificare le regioni ErrScan = ScansioneMatrice(i, ScanDoc[i].TotCol - MetalDetection.SensorsDelay); } if (++ScanDoc[i].TotCol == MTL_SCAN_COLS) { // Ho superato la dimensione massima del buffer: chiudo la scansione // documento abilitando la lettura solo della seconda barriera // printf("\nRaggiunto limite su buffer %d\n",i); MetalCounter[i].EndDoc = MetalDetection.SensorsDelay; MetalCounter[i].Broken = 1; MetalCounter[i].StopCount = NO_COUNT; } // Inizializzo il contatore per la prossima scansione MetalCounter[i].Timer = MetalDetection.Timing; } else // if (MetalCounter[i].EndDoc == NO_ENDDOC) { // Siamo a fine documento: completo la lettura salvando sulla // matrice di scansione solo la seconda barriera di sensori ScanMatrix[i][1][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 1) & 0x0001; ScanMatrix[i][3][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 3) & 0x0001; ScanMatrix[i][5][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 5) & 0x0001; ScanMatrix[i][7][ScanDoc[i].TotCol - MetalDetection.SensorsDelay] = (metaldata >> 7) & 0x0001; // Analizzo la colonna appena completata per identificare le regioni ErrScan = ScansioneMatrice(i, ScanDoc[i].TotCol - MetalDetection.SensorsDelay); // Decremento il contatore di fine documento MetalCounter[i].EndDoc--; if (MetalCounter[i].EndDoc) { //to be continued
Here the 4/5 part of the code:
// Continuo la chiusura lettura documento ScanDoc[i].TotCol++; // Inizializzo il contatore per la prossima scansione MetalCounter[i].Timer = MetalDetection.Timing; } else { // printf("\nFine scansione su buffer %d\n",i); // La scansione del documento e' terminata MetalDetection.LastRead = i; ScanDoc[i].TotCol -= (MetalDetection.SensorsDelay - 1); MetalCounter[i].Active = 0; MetalCounter[i].EndDoc = NO_ENDDOC; MetalCounter[i].Timer = NO_COUNT; MetalCounter[i].EquEnable = 1; MetalDetection.BufAvailable = 1; // Viene aggiornato lo stato della scheda secondo lo // stato della memoria di allocazione dinamica, ma non // viene generato un report dello stato slave, pertanto // il nuovo stato verra' trasmesso al primo invio // programmato if (ErrMemory) { Stato |= ERROR_MTL; } else { Stato &= ~ERROR_MTL; } } } // if (MetalCounter[i].EndDoc == NO_ENDDOC) // Disabilito la lettura sensori MetalCounter[i].ReadEnable = 0; } //if (MetalCounter[i].ReadEnable) } // for (i = 0; i < MTL_BUFNUM; i++) // **************** ELABORAZIONI RICERCA METALLI ********************* for (i = 0; i < MTL_BUFNUM; i++) { // Sezione 3 - Normalizzazione equivalenze if (MetalCounter[i].EquEnable) { MetalCounter[i].EquEnable = 0; ErrEqu = NormalizzaEquivalenze(i); MetalCounter[i].LabEnable = 1; // printf("\nNormalizzazione equivalenze eseguita su buffer %d\n",i); } //if (MetalCounter[i].EquEnable) // Sezione 4 - Normalizzazione etichette if (MetalCounter[i].LabEnable) { MetalCounter[i].LabEnable = 0; ErrLab = NormalizzaEtichette(i); MetalCounter[i].CatEnable = 1; // printf("\nNormalizzazione etichette eseguita su buffer %d\n",i); } //if (MetalCounter[i].LabEnable) // Sezione 5 - Catalogazione etichette if (MetalCounter[i].CatEnable) { MetalCounter[i].CatEnable = 0; ErrCat = CatalogaEtichette(i); MetalDetection.LastComplete = i; ErrDel = EliminaEquivalenze(i); printf("\n TotCol per buffer %d = %d\n",i, ScanDoc[i].TotCol); /* printf(" SamplesCount per buffer %d = %d\n",i, ScanDoc[i].SamplesCount); printf(" RegionsCount per buffer %d = %d\n",i, ScanDoc[i].RegionsCount); printf(" NumRegions per buffer %d = %d\n",i, ScanDoc[i].NumRegions); printf(" LargerRegionSamples per buffer %d = %d\n",i, ScanDoc[i].LargerRegionSamples); printf(" HigherRegionHeight per buffer %d = %d\n",i, ScanDoc[i].HigherRegionHeight); printf(" HigherRegionLength per buffer %d = %d\n",i, ScanDoc[i].HigherRegionLength); printf(" LongerRegionHeight per buffer %d = %d\n",i, ScanDoc[i].LongerRegionHeight); printf(" LongerRegionLength per buffer %d = %d\n\n\n",i, ScanDoc[i].LongerRegionLength); */ // Set del bit di dato valido MetalCounter[i].Valid = 1; MetalCounter[i].CountValid = MetalDetection.DlyValid; // Abilitazione invio report LENTO1 MetalDetection.SendRepEnable = 1; // Se la gestione e' a spazio leggo lo stato dell'encoder if (MetalDetection.Encoder != 0xFF) MetalCounter[i].EncPrev = ENCPORT[0]; } //if (MetalCounter[i].CatEnable) } // for (i = 0; i < MTL_BUFNUM; i++) } // if (MetalDetection.Enable) // =============== GESTIONE RICERCA METALLI: FINE ==================== countEnc = ENCPORT[0]; //to be continued
Here the 5/5 part of the code:
// ================== GESTIONE RILETTURA USCITE ====================== if (NOutputSpeed) { if (!RB_Cnt) { // controllo della rilettura di tutte le uscite checkRB = ((~Output) ^ P5) & MaskOutSpeed; for (i=0; i<NOutputSpeed; i++) { if (EnableRB[i] && (checkRB & (1<<i))) { CountErrRB++; errRB =1; } } RB_Cnt = NO_COUNT; } if (RB_Cnt != NO_COUNT) RB_Cnt--; } // ===================== GESTIONE RITARDI =========================== if (NDly) { // gestione canali ritardati for (i=0; i<NDly; i++) { // se nel ciclo precedente è cambiato lo stato dell'uscita viene // controllato se si è verificato un errore di rilettura (se abilitata) if(EnableRB[Dly[i].Output] && (!Dly[i].Status)) { if(((~Output) ^ P5) & (0x0001 << Dly[i].Output)) { CountErrRB++; errRB = 1; } Dly[i].Status = NO_COUNT; } if (Dly[i].Status != NO_COUNT) Dly[i].Status--; if (Dly[i].Encoder == 0xFF) { // -------------- Ritardi a tempo ------------------------------- if (Dly[i].CountDlyOn != NO_COUNT) { Dly[i].CountDlyOn--; if (Dly[i].CountDlyOn < 0) { Output |= (0x0001 << Dly[i].Output); Dly[i].Status = RB_DELAY; Dly[i].CountDlyOn = NO_COUNT; } } if (Dly[i].CountDlyOff != NO_COUNT) { Dly[i].CountDlyOff--; if (Dly[i].CountDlyOff < 0) { Output &= ~(0x0001 << Dly[i].Output); Dly[i].Status = RB_DELAY; Dly[i].CountDlyOff = NO_COUNT; } } } else { // -------------- Ritardi a spazio (encoder) ---------------------- if (Dly[i].CountDlyOn != NO_COUNT) { cnt = abs(countEnc - countON[i]); if (cnt > MAX_GAP) Dly[i].CountDlyOn -= (countEnc > MAX_GAP) ? (0xFF - countEnc + countON[i]): (0xFF + countEnc - countON[i]); else Dly[i].CountDlyOn -= cnt; // Dly[i].CountDlyOn -= abs(countEnc - countON[i]); countON[i] = countEnc; if (Dly[i].CountDlyOn <= 0) { Output |= (0x0001 << Dly[i].Output) ; Dly[i].Status = RB_DELAY; Dly[i].CountDlyOn = NO_COUNT; } } if (Dly[i].CountDlyOff != NO_COUNT) { cnt = abs(countEnc - countOFF[i]); if (cnt > MAX_GAP) Dly[i].CountDlyOff -= (countEnc > MAX_GAP) ? (0xFF - countEnc + countOFF[i]): (0xFF + countEnc - countOFF[i]); else Dly[i].CountDlyOff -= cnt; // Dly[i].CountDlyOff -= abs(countEnc - countOFF[i]); countOFF[i] = countEnc; if (Dly[i].CountDlyOff <= 0) { Output &= ~(0x0001 << Dly[i].Output); Dly[i].Status = RB_DELAY; Dly[i].CountDlyOff = NO_COUNT; } } } } // attuazione dei canali di uscita SetOut(Output); } // trasmissione su CAN della condizione di errore sul PDO di stato // se si è verificato almeno un errore di rilettura if (errRB && (!(Stato & ERROR_RB))) { T8R = 1; Stato |= ERROR_RB; CAN_MSGOBJ[STATO].msg_ctl = CPUUPD_SET; CAN_MSGOBJ[STATO].msg_cfg = MSG_CFG(1, CANDIR_TRANSMIT, 0); CAN_MSGOBJ[STATO].msg[0] = Stato; CAN_MSGOBJ[STATO].msg_ctl = CPUUPD_CLR & TXRQ_SET; } StartT1Idle = T1; }