Hi!
I've been working with the IPC protocol for some time and I have been using the IPC Flag 0 for interrupting the CPU2 from the CPU1. However, for initial configurations of some parameters in the CPU1 process, I need to use another IPC flag with interrupting capabilities for CPU2, for which I'm trying using IpcCPU1toCPU2Regs.CPU1TOCPU2IPCFLG.IPC1.
My problem is when debugging, during the first initialization steps, I see that the function "IPC_setFlagLtoR" doesn't set the bit to 1, hence the "IPC_waitForAck" doesn't do anything. I have realized a couple of things when trying out different things:
- Using Flag 1 in CPU1 and any other flag but flag 1 in CPU2, Flag1 goes to 1 and "IPC_waitForAck" waits = OK
- Using the same flag in both CPUs, "IPC_setFlagLtoR" doesn't set flag X to 1 = Not OK
Note that I have also used the Flag 31 to synchronize both CPUs to let them both initialize their hardware and other things.
This is my code for the initialization part of the main routine for CPU1:
void main(void) { // Initialize device clock and peripherals. Device_init(); //_______________________________________________________________________________________________________________________________________________ // BOOT DEL CORE 2 EN FLASH O RAM //_______________________________________________________________________________________________________________________________________________ #ifdef triggersEnable #ifdef _FLASH Device_bootCPU2(BOOTMODE_BOOT_TO_FLASH_SECTOR0); #else Device_bootCPU2(BOOTMODE_BOOT_TO_M0RAM); #endif #endif // // Disable all the interrupts. DINT; // // Setup GPIO by disabling pin locks and enabling pullups. Device_initGPIO(); #ifdef triggersEnable initSPI4SD(); #endif // Initialize PIE and clear PIE registers. Disables CPU interrupts. Interrupt_initModule(); // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). Interrupt_initVectorTable(); //-----------------------------------------------------IMPORTANTE--------------------------------------------------------------- //--------------------------- (BOARD_INIT EJECUTA TODA LA CONFIGURACION DEFINIDA EN EL SYSCONFIG)------------------------------- //-----------------------------------------------(FICHEROS board.c y board.h)--------------------------------------------------- Board_init(); //_______________________________________________________________________________________________________________________________________________ // INICIO IPC //_______________________________________________________________________________________________________________________________________________ #ifdef triggersEnable IPC_clearFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG_ALL); // Clear any IPC flags if set already IPC_sync(IPC_CPU1_L_CPU2_R, IPC_FLAG31); // Synchronize both the cores. Borrar? #endif //_______________________________________________________________________________________________________________________________________________ // DAR CONTROL DE RAMGS A CADA CORE //_______________________________________________________________________________________________________________________________________________ #ifdef triggersEnable MemCfg_setGSRAMControllerSel((MEMCFG_SECT_GS10 | MEMCFG_SECT_GS11), MEMCFG_GSRAMCONTROLLER_CPU1); // Give memory access to GS10 and GS11 RAM to CPU1 and GS12, GS13 and GS14 to CPU2 MemCfg_setGSRAMControllerSel((MEMCFG_SECT_GS12 | MEMCFG_SECT_GS13 | MEMCFG_SECT_GS14), MEMCFG_GSRAMCONTROLLER_CPU2); #endif //_______________________________________________________________________________________________________________________________________________ // CONFIGURACION DEL DAC //_______________________________________________________________________________________________________________________________________________ myDACA_init(); //DACA myDACB_init(); //DACB myDACC_init(); //DACC //__________________________________________________________________________________________________________________________________________________ // CONFIGURACION EQEP ENCODER MODULE //__________________________________________________________________________________________________________________________________________________ EQEP_config(EQEP_BASE_SELECT); //____________________________________________________________________________________________________________________________________________________ // CONFIGURACION DEL EMIF //____________________________________________________________________________________________________________________________________________________ //Estructura para par�metros de tiempos de R/W del EMIF EMIF_AsyncTimingParams tparam; // Configure to run EMIF1 on full Rate. (EMIF1CLK = CPU1SYSCLK) SysCtl_setEMIF1ClockDivider(SYSCTL_EMIF1CLK_DIV_1); // Grab EMIF1 For CPU1. EMIF_selectController(EMIF1CONFIG_BASE, EMIF_CONTROLLER_CPU1_G); // Disable Access Protection. (CPU_FETCH/CPU_WR/DMA_WR) EMIF_setAccessProtection(EMIF1CONFIG_BASE, 0x0); // Commit the configuration related to protection. Till this bit remains // set, contents of EMIF1ACCPROT0 register can't be changed. EMIF_commitAccessConfig(EMIF1CONFIG_BASE); // Lock the configuration so that EMIF1COMMIT register can't be changed // any more. EMIF_lockAccessConfig(EMIF1CONFIG_BASE); // Configure GPIO pins for EMIF1. setupEMIF1PinmuxAsync16Bit(); //PINES USADOS POR EL EMIF -- IMPORTANTE FUNCION!! // Configures Normal Asynchronous Mode of Operation. EMIF_setAsyncMode(EMIF1_BASE, EMIF_ASYNC_CS4_OFFSET, //CAMBIO V2 PARA USAR CS4 EN VEZ DE CS3 EMIF_ASYNC_NORMAL_MODE); // Disables Extended Wait Mode. EMIF_disableAsyncExtendedWait(EMIF1_BASE, EMIF_ASYNC_CS4_OFFSET);//CAMBIO V2 PARA USAR CS4 EN VEZ DE CS3 // Configure EMIF1 Data Bus Width. EMIF_setAsyncDataBusWidth(EMIF1_BASE, EMIF_ASYNC_CS4_OFFSET, //CAMBIO V2 PARA USAR CS4 EN VEZ DE CS3 EMIF_ASYNC_DATA_WIDTH_8); //O PONER A 8 AUNQUE LUEGO PONER A 16 PARA EVITAR EL TURN-AROUND TIME. CUANDO SE USE EL ADC REAL, CAMBIAR A 8 EL DATAWIDTH // // Configure the access timing for CS4 space. // tparam.rSetup = 3;//5; //3 tparam.rStrobe = 11;//15; //11 tparam.rHold = 7;//6; //5 tparam.turnArnd = 5;//5; //3 tparam.wSetup = 3;//5; //3 tparam.wStrobe = 7;//15; //7 tparam.wHold = 6;//6; //4 EMIF_setAsyncTimingParams(EMIF1_BASE, EMIF_ASYNC_CS4_OFFSET, &tparam); //CAMBIO V2 PARA USAR CS4 EN VEZ DE CS3 // FUNCION DE CONFIGURACION DE GPIOS PARA EL ADC-EMIF setupGPIOcomEMIF_ADC(); //________________________________________________________________________________________________________________________________________________ // AJUSTE TRAMAS Y CONFIGURACION ADC //_________________________________________________________________________________________________________________________________________________ ajustetodastramasADC(); configurarADC(tramaConfADC_SEQEN_BURST, 10, tramaFiltroPasoBajo376, 8); lect_ConfADC=0x0004; // LEE CONF ADC lect_RangoADC_0_3_A=0x0008; //LEE EL RANGO DEL ADCA CANAL 0-3 lect_RangoADC_0_3_B=0x000C; //LEE EL RANGO DEL ADCB CANAL 0-3 lect_RangoADC_4_7_A=0x000A; //LEE EL RANGO DEL ADCA CANAL 4-7 lect_RangoADC_4_7_B=0x000E; //LEE EL RANGO DEL ADCB CANAL 4-7 lect_FPBADC=0x001A; //LEE FILTRO PB //lect_CHADC=0x0006; res_lectConfADC=leerRegADC(lect_ConfADC,tamanobusdatos); res_lectRango_03A_ADC=leerRegADC(lect_RangoADC_0_3_A,tamanobusdatos); res_lectRango_03B_ADC=leerRegADC(lect_RangoADC_0_3_B,tamanobusdatos); res_lectRango_47A_ADC=leerRegADC(lect_RangoADC_4_7_A,tamanobusdatos); res_lectRango_47B_ADC=leerRegADC(lect_RangoADC_4_7_B,tamanobusdatos); res_lectFPBADC=leerRegADC(lect_FPBADC,tamanobusdatos); //res_lectCHADC=leerRegADC(lect_CHADC,tamanobusdatos); res_lectConfADC=ajustetramaADC(res_lectConfADC); res_lectRango_03A_ADC=ajustetramaADC(res_lectRango_03A_ADC); res_lectRango_03B_ADC=ajustetramaADC(res_lectRango_03B_ADC); res_lectRango_47A_ADC=ajustetramaADC(res_lectRango_47A_ADC); res_lectRango_47B_ADC=ajustetramaADC(res_lectRango_47B_ADC); res_lectFPBADC=ajustetramaADC(res_lectFPBADC); // res_lectCHADC=ajustetramaADC(res_lectCHADC); if(SEQEN==1){ lectSTACK0=0x0040; lectSTACK1=0x0042; lectSTACK2=0x0044; lectSTACK3=0x0046; lectSTACK4=0x0048; lectSTACK5=0x004A; lectSTACK6=0x004C; lectSTACK7=0x004E; reslectSTACK0=leerRegADC(lectSTACK0,tamanobusdatos); reslectSTACK1=leerRegADC(lectSTACK1,tamanobusdatos); reslectSTACK2=leerRegADC(lectSTACK2,tamanobusdatos); reslectSTACK3=leerRegADC(lectSTACK3,tamanobusdatos); reslectSTACK4=leerRegADC(lectSTACK4,tamanobusdatos); reslectSTACK5=leerRegADC(lectSTACK5,tamanobusdatos); reslectSTACK6=leerRegADC(lectSTACK6,tamanobusdatos); reslectSTACK7=leerRegADC(lectSTACK7,tamanobusdatos); reslectSTACK0=ajustetramaADC(reslectSTACK0); reslectSTACK1=ajustetramaADC(reslectSTACK1); reslectSTACK2=ajustetramaADC(reslectSTACK2); reslectSTACK3=ajustetramaADC(reslectSTACK3); reslectSTACK4=ajustetramaADC(reslectSTACK4); reslectSTACK5=ajustetramaADC(reslectSTACK5); reslectSTACK6=ajustetramaADC(reslectSTACK6); reslectSTACK7=ajustetramaADC(reslectSTACK7); } //____________________________________________________________________________________________________________________________________________ // AJUSTE TIMERS INTERRUPCION //_____________________________________________________________________________________________________________________________________________ if(SEQEN==1){ if(BURSTMODE==1){ Interrupt_register(INT_TIMER0, &cpuTimer0ISR_SEQEN_BURST); } } initCPUTimer0(); if(SEQEN==0){ configCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, 1000); } else if(SEQEN==1){ if(BURSTMODE==1){ configCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, Ts_us); //TIEMPO EN MICROSEGUNDOS 200us } else configCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, Ts_us); } CPUTimer_enableInterrupt(CPUTIMER0_BASE); Interrupt_enable(INT_TIMER0); //_____________________________________________________________________________________________________________________________________________ // CONFIGURACION MODULO PWM //______________________________________________________________________________________________________________________________________________ // SE DESACTIVA LA SENAL DE RELOJ DEL TIME-BASE DEL MODULO PWM SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); configPWM_module_outputsignals(faseR_recv_BASE, TBPRD_recv); configPWM_module_outputsignals(faseS_recv_BASE, TBPRD_recv); configPWM_module_outputsignals(faseT_recv_BASE, TBPRD_recv); configPWM_module_outputsignals(faseR_rotor_BASE, TBPRD_rotor); configPWM_module_outputsignals(faseS_rotor_BASE, TBPRD_rotor); configPWM_module_outputsignals(faseT_rotor_BASE, TBPRD_rotor); // Se desactivan los relojes de los modulos PWM utilizados SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM1); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM2); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM3); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM4); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM5); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_EPWM6); // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) //EDIS; EINT; ERTM; SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); CPUTimer_startTimer(CPUTIMER0_BASE); GPIO_writePin(enableControlOutputPin,0); //_______________________________________________________________________________________________________________________________________________ // INICIALIZO VARIABLE TRIGGERS //________________________________________________________________________________________________________________________________________________ #ifdef triggersEnable FlTrigg = 0; #endif // // Activo Flag del IPC para pedir los datos del motor a la CPU2 guardados en SD. La CPU2 los guarda en // IPC_setFlagLtoR(IPC_CPU1_L_CPU2_R, IPC_FLAG1); IPC_waitForAck(IPC_CPU1_L_CPU2_R, IPC_FLAG1); [...]
Initialization code of CPU2:
void main(void) { uint16_t i; FRESULT errorSD; FILINFO structInfo; uint8_t fileName[tamFileName], fileNameBorrar[tamFileName], *pBorrar; // // Initialize device clock and peripherals // Device_init(); // // Disable pin locks and enable internal pullups. // Device_initGPIO(); // // Initialize PIE and clear PIE registers. Disables CPU interrupts. // Interrupt_initModule(); // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // Interrupt_initVectorTable(); // // Enable CPU Timer 0 interrupt // Interrupt_enable(INT_TIMER0); // // Clear any IPC flags if set already // IPC_clearFlagLtoR(IPC_CPU2_L_CPU1_R, IPC_FLAG_ALL); // // Enable IPC interrupts // IPC_registerInterrupt(IPC_CPU2_L_CPU1_R, IPC_INT0, IPC_ISR0); //Flag0 del IPC para recibir una medida cada triggSampleRate*200us IPC_registerInterrupt(IPC_CPU2_L_CPU1_R, IPC_INT3, IPC_motorParams); //Flag1 del IPC para interrupcion para pedir parametros del motor de la SD // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; SDFatFS_init(); SDFatFS_Handle sdFatFs_handle = SDFatFS_open(sdspiHandle, DRIVE_NUM); if (sdFatFs_handle == NULL) { while(1); } // Synchronize both the cores. // IPC_sync(IPC_CPU2_L_CPU1_R, IPC_FLAG31); contNewSamples = 0; aux = 0; // // Loop indefinitely // while(1) { [...]
Interrupt function "IPC_motorParams" in CPU2:
__interrupt void IPC_motorParams(){ motor1.fgrid = Pavlikfgrid; motor1.Pn_motor = PavlikPn_motor; motor1.p_motor = Pavlikp_motor; motor1.Vrot = PavlikVrot; motor1.Vg_ph_ph = PavlikVg_ph_ph; motor1.Jmotor = PavlikJmotor; motor1.gearbox = Pavlikgearbox; motor1.w_sincro = Pavlikw_sincro; motor1.TL_nominal = PavlikTL_nominal; motor1.TL_max = PavlikTL_max; motor1.overload_max = Pavlikoverload_max; motor1.w_grid = 2.0*pi*motor1.fgrid; motor1.m_motor = motor1.Vg_ph_ph/motor1.Vrot; // Relacion de transformacion del motor motor1.m_motor_1 = motor1.Vrot/motor1.Vg_ph_ph; motor1.R1motor = 0.03292 ; // Resistencia del estator motor1.L1motor = (0.6221/(2*pi*motor1.fgrid)); // Inductancia del estator motor1.R2motor = 0.038 ; // Resistencia del rotor referida al estator motor1.L2motor = (0.8476/(2*pi*motor1.fgrid)); // Inductancia del rotor referida al estator motor1.Lm_motor = (22.80/(2*pi*motor1.fgrid)) ; // Inductancia mutua o magnetizante motor1.Ls = (motor1.Lm_motor+motor1.L1motor); motor1.Lr = (motor1.Lm_motor+motor1.L2motor); motor1.sigma = 1-((motor1.Lm_motor*motor1.Lm_motor)/(motor1.Ls*motor1.Lr)); motor1.Flux_s = (motor1.Vg_ph_ph*raiz_2/raiz_3)/(2*pi*motor1.fgrid); // Flujo magnetico del estator motor1.Leq_recv = 0.0005445567972672212; //L_recv // // Acknowledge the flag // IPC_ackFlagRtoL(IPC_CPU2_L_CPU1_R, IPC_FLAG1); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1); }
The interrupt in CPU2 doesn't execute in this case since the Flag 1 doesn't go to 1. And the CPU2 code just checks on loop other variables not related to this issue. What am I missing?