This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
I am using PI controller for DC-DC converter control. When this line " uk_V = DCL_runPI(&pi1, rk, yk); " is executed, the compiler jumps to illegal ISR. and when debugged says the error " cannot load from non-primitive location". Though all the variables ( uk, rk, yk) have same data type "float". The compiler also gives warning "warning #10247-D: creating output section "dclfuncs" without a SECTIONS "
Kindly Help.
Thanking you in advance.
I can tell from the function name you are using v1.0 of the library. I recommend updating to the latest v3.0 which you can find in C2000Ware. The equivalent function in the newer library is DCL_runPI_C1.
The warning is telling you that there's no allocated memory for the controller. You'll need to add a line to your linker command file to tell the linker where to place that section. Something like:
dclfuncs : > RAML4, PAGE = 0
The newer library has several working examples, so it may help to look through those to see how this is done.
Possibly the "non-primitive" error has to do with the above, but check also that you have declared your "pi1" controller structure correctly and that it is visible to the function.
Regards,
Richard
Hey Richard,
As you suggested I updated the latest version v3.0. But it doesn't work for me. To remove the warning I included command in linker file. But it gives me the error as attached in the image. But, I don't find any other linker command file, then why it gives me error of "more than one linker command file". Regarding, Non-primitive location, I have defined them correctly. but For you to look into it, I am attaching my program.
Thanking you for your support.
Regards,
Vidhi
// // Included Files // #include "F28x_Project.h" #include "DCLF32.h" // // Defines // //#define ONE (4095) // in 2^12 format // // Function Prototypes // void InitEPwm1(void); void InitEPwm2(void); __interrupt void epwm1_isr(void); __interrupt void epwm2_isr(void); interrupt void int_ext(void); //timetick associato al pin 42 //variables //int i = 0; int j = 0; //int k = 0; float PI_OUTPUT; //float error; //float V_array[600]; float adc_volt[10]; float adc_cur[10]; float sum_V=0; float sum_I=0; float Volt_final; float Curr_final; float offset_V = 200; float offset_I = 128; float DUTY_cycle = 0.5; void adc_config(); void SetupADCSoftwareSync(void); #define EPWM1_TIMER_TBPRD 1667 // Period register //#define EPWM1_CMPA 5000 #define EPWM1_DB 20; // for 500 ns of deadband #define PI_VALUES_V {0.06f, 0.1f, 0.1f, 1.0f, -1.0f, 0.1f} // Kp, Ki, i10, Sat_max, Sat_min, Sat_storage float rk_V; // Reference value float yk_V; // Measured ADC signal float uk_V; // PI output DCL_PI pi1 = PI_VALUES_V; float V_ref=100; int enable=0; // PI controller variables for current controller #define PI_VALUES_I {0.06f, 0.1f, 0.1f, 1.0f, 0.0f, 0.1f} // Kp, Ki, i10, Sat_max, Sat_min, Sat_storage float rk_I; // Reference value float yk_I; // Measured ADC signal float uk_I; // PI output //float lk_I = 0.0f; // saturation DCL_PI pi2 = PI_VALUES_I; Uint32 EPwm2TimerIntCount =0; Uint32 EPwm1TimerIntCount =0; Uint32 count = 0; void main(void) { InitSysCtrl(); // InitGpio(); // // enable PWM1, PWM2 // CpuSysRegs.PCLKCR2.bit.EPWM1=1; CpuSysRegs.PCLKCR2.bit.EPWM2=1; // For this case just init GPIO pins for ePWM1, ePWM2, ePWM3 // These functions are in the F2837xD_EPwm.c file // InitEPwm1Gpio(); InitEPwm2Gpio(); //Clear all interrupts and initialize PIE vector table: //Disable CPU interrupts DINT; InitPieCtrl(); //Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; InitPieVectTable(); //User specific code: //Interrupts are not used in this example. // // Map ISR functions // EALLOW; PieVectTable.EPWM1_INT = &epwm1_isr; PieVectTable.EPWM2_INT = &epwm2_isr; PieVectTable.XINT1_INT = &int_ext; EDIS; // Initialize the Device Peripherals: // EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0; EDIS; // // Configure the ePWM // InitEPwm1(); InitEPwm2(); EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =1; EDIS; // // Enable CPU INT3 which is connected to EPWM1-3 INT: // IER |= M_INT3; // // Enable EPWM INTn in the PIE: Group 3 interrupt 1-3 // PieCtrlRegs.PIEIER3.bit.INTx1 = 1; PieCtrlRegs.PIEIER3.bit.INTx2 = 1; // // Enable global Interrupts and higher priority real-time debug events: // EINT; // Enable Global interrupt INTM ERTM; // Enable Global real time interrupt DBGM // // Enable XINT1 and XINT2 in the PIE: Group 1 interrupt 4 & 5 // Enable INT1 which is connected to WAKEINT: // PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // Enable PIE Group 1 INT4 PieCtrlRegs.PIEIER1.bit.INTx5 = 1; // Enable PIE Group 1 INT5 IER |= M_INT1; // Enable CPU INT1 EINT; // Enable Global Interrupts // // GPIO0 is XINT1 // GPIO_SetupXINT1Gpio(42); //timetick 1 // // Configure XINT1 // XintRegs.XINT1CR.bit.POLARITY = 1; // Rising edge interrupt // // Enable XINT1 // XintRegs.XINT1CR.bit.ENABLE = 1; // Enable XINT1 // // Configure the ADC and power it up adc_config(); SetupADCSoftwareSync(); EALLOW; GpioCtrlRegs.GPBMUX1.bit.GPIO42 = 0; // GPIO 42 TimeTick 1 GpioCtrlRegs.GPBDIR.bit.GPIO42 = 0; // input QUI DECIDI LA DIR DELL'INTERRUpt GpioCtrlRegs.GPBQSEL1.bit.GPIO42 = 0; // XINT1 Synch to SYSCLKOUT only GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 0; GpioCtrlRegs.GPCDIR.bit.GPIO64 = 1; //PIN OUT GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 0; GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 0; GpioCtrlRegs.GPCDIR.bit.GPIO65 = 1; //PIN OUT GpioCtrlRegs.GPCQSEL1.bit.GPIO65 = 0; GpioDataRegs.GPCCLEAR.bit.GPIO64 = 1; GpioDataRegs.GPCCLEAR.bit.GPIO65 = 1; DELAY_US(1000000); GpioDataRegs.GPCSET.bit.GPIO64 = 1; GpioDataRegs.GPCSET.bit.GPIO65 = 1; DELAY_US(5000); EDIS; for(;;) { count++; } } __interrupt void epwm1_isr(void) { j++; // GpioDataRegs.GPCSET.bit.GPIO71 =1; // GpioDataRegs.GPCSET.bit.GPIO70 =1; // AdcaRegs.ADCSOCFRC1.all = 0x000F; // AdcbRegs.ADCSOCFRC1.all = 0x000F; AdccRegs.ADCSOCFRC1.all = 0x000F; AdcdRegs.ADCSOCFRC1.all = 0x000F; adc_volt[j] = (AdccResultRegs.ADCRESULT0-offset_V)*650/4095 ; // read dc-link voltage adc_cur[j] = (2048-(AdcdResultRegs.ADCRESULT0+offset_I))*35/2048; // read inductor current value sum_V = adc_volt[j]+sum_V; sum_I = adc_cur[j]+sum_I; if(j==10){ Volt_final = sum_V/10; Curr_final = sum_I/10; sum_V=0; sum_I=0; j=0; } if(enable==1){ yk_V = Volt_final/400 ; // dc-link voltage should be within 400 V yk_I = Curr_final/20 ; // inductor current should be within 20 A rk_V = V_ref/400; //============================== voltage and current PI controller =====================// uk_V = DCL_runPI_C1(&pi1, rk_V, yk_V); rk_I = uk_V; uk_I = DCL_runPI_C1(&pi2, rk_I, yk_I); //========================================================================// // // error = (rk_V-(float)(AdcaResultRegs.ADCRESULT0)) ; PI_OUTPUT = (uk_I*EPwm2Regs.TBPRD); // change to uk_I for BDC DUTY_cycle = ((int)PI_OUTPUT)/( EPwm2Regs.TBPRD); EPwm2Regs.CMPA.bit.CMPA = PI_OUTPUT; } EPwm1TimerIntCount++; // Clear INT flag for this timer // EPwm1Regs.ETCLR.bit.INT = 1; // //Acknowledge this interrupt to receive more interrupts from group 3 // PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; // GpioDataRegs.GPCCLEAR.bit.GPIO71 =1; // GpioDataRegs.GPCCLEAR.bit.GPIO70 =1; } void adc_config(){ EALLOW; // //write configurations // AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdccRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdcdRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); AdcSetMode(ADC_ADCC, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); AdcSetMode(ADC_ADCD, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); // // AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; //power up the ADCs // AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1; AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1; AdcdRegs.ADCCTL1.bit.ADCPWDNZ = 1; // //delay for 1ms to allow ADC time to power up // DELAY_US(1000); EDIS; } interrupt void int_ext(void) { enable = 1; // GpioDataRegs.GPBCLEAR.bit.GPIO42 =1; // // Acknowledge this interrupt to get more from group 1 // PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; } void SetupADCSoftwareSync(void) { Uint16 acqps; // //determine minimum acquisition window (in SYSCLKS) based on resolution // if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION) { acqps = 14; //75ns } else //resolution is 16-bit { acqps = 63; //320ns } if(ADC_RESOLUTION_12BIT == AdcbRegs.ADCCTL2.bit.RESOLUTION) { acqps = 14; //75ns } else //resolution is 16-bit { acqps = 63; //320ns } if(ADC_RESOLUTION_12BIT == AdccRegs.ADCCTL2.bit.RESOLUTION) { acqps = 14; //75ns } else //resolution is 16-bit { acqps = 63; //320ns } if(ADC_RESOLUTION_12BIT == AdcdRegs.ADCCTL2.bit.RESOLUTION) { acqps = 14; //75ns } else //resolution is 16-bit { acqps = 63; //320ns } // //Select the channels to convert and end of conversion flag // EALLOW; AdcaRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC1 will convert pin B2 (Lac lato sx 2.632V= 35A) AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + AdcbRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC1 will convert pin B2 (Lac lato sx 2.632V= 35A) AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + AdccRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC1 will convert pin B2 (Lac lato sx 2.632V= 35A) AdccRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + AdcdRegs.ADCSOC0CTL.bit.CHSEL = 2; //SOC1 will convert pin B2 (Lac lato sx 2.632V= 35A) AdcdRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + //1 SYSCLK cycles EDIS; } void InitEPwm1() { //used for ISR EPwm1Regs.TBPRD = 500; // Set timer period for f=10 KHz EPwm1Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0 EPwm1Regs.TBCTR = 0x0000; // Clear counter // // Setup TBCLK // EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up DOWN EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading EPwm1Regs.TBCTL.bit.HSPCLKDIV =TB_DIV1; // Clock ratio to SYSCLKOUT EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // // Setup compare // EPwm1Regs.CMPA.bit.CMPA = 250; // // Set actions // //Uncomment "ZRO" when run on 28379D // EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Set PWM1A on Zero EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on Zero EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR; // Set PWM1A on Zero EPwm1Regs.AQCTLB.bit.CAD = AQ_SET; // Active High complementary PWMs - setup the deadband // EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL; EPwm1Regs.DBRED.bit.DBRED = EPWM1_DB; EPwm1Regs.DBFED.bit.DBFED = EPWM1_DB; // // Interrupt where we will change the Deadband // EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 3rd event } void InitEPwm2() { //used for PWM operation EPwm2Regs.TBPRD = 1667; // frequency of ISR at 100kHz EPwm2Regs.TBPHS.bit.TBPHS = 0x0000; // Phase is 0 EPwm2Regs.TBCTR = 0x0000; // Clear counter // // Setup TBCLK // EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up DOWN EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading EPwm2Regs.TBCTL.bit.HSPCLKDIV =TB_DIV1; // Clock ratio to SYSCLKOUT EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1; // // Setup compare EPwm2Regs.CMPA.bit.CMPA = DUTY_cycle* 1667; // // Set actions // EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on Zero EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Set PWM1A on Zero //EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm2Regs.AQCTLB.bit.CAU = AQ_CLEAR; // Set PWM1A on Zero EPwm2Regs.AQCTLB.bit.CAD = AQ_SET; // Active High complementary PWMs - setup the deadband // EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL; EPwm2Regs.DBRED.bit.DBRED = EPWM1_DB; EPwm2Regs.DBFED.bit.DBFED = EPWM1_DB; // // Interrupt where we will change the Deadband // EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm2Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 3rd event } __interrupt void epwm2_isr(void) { EPwm2TimerIntCount++; // // Clear INT flag for this timer // EPwm2Regs.ETCLR.bit.INT = 1; // // Acknowledge this interrupt to receive more interrupts from group 3 // PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }
Hey Richard,
The program doesn't give the error directly. Because first time when program runs "enable = 0" , so program does not move inside DCL_PI function (line 229 in code). Now, when I put enable = 1 in watch expression manually, after the program is building successfully, it will go inside loop and will jump to illegal ISR and stops at line 235 in code. Kindly have a look in image attached. Before, when I put cursor on the uk_V, in the value parameter it said "cannot load from non primitive location." But now it shows in the value "0.00".
Regarding, Linker command file, I checked in the properties but I do not find any other linker command file.
Thanking you.
Regards,
Vidhi
Hi Vidhi,
For the symbol re-definition error, those labels would be defining the addresses of functions you want to load into RAM. They must be in more than one place in your project or the compiler would not generate the warning. Can you do a search through your linker, source, and header files to check where they appear? Normally they would be defined in the linker file, extern'ed in a header file, and referenced in a memcopy() function. Check the flash example in the C2000Ware header files to see how this is done.
Did you look at the last item in my previous post? When I was stepping through your code afterwards I noticed the controller doesn't work unless you have the right number of initializers. Please look at this again. You should have ten initializers in PI_VALUES_I and PI_VALUES_V.
Regards,
Richard
Dear Richard,
I am sorry to say but, I defined 10 parameters for PI_VALUES_V and PI_VALUES_I, and still its the same issue. If I use linker command file it still gives me error of duplicate allocation of memory. But, I go through source, header and linker files and I do not find linker files more than one. May I ask which linker command file are you using? I tried using "2837xS_Generic_RAM_lnk.cmd"and also "28377S_RAM_lnk.cmd, but then also the errors.
I think its the problem related to memory and not code.
I noticed another thing when I try to debug that "where it stops and why" and, I found that it stops in file "DCL_PI_C1.asm" at line 28, as it do not find the value of R4H ( as seen in image attached) , R5H, R6H and jumps to illegal ISR. Kindly guide me that how to find these values and also if I have to give some address instead of "NULL_ADDR" in defining " PI_VALUES_V" and "PI_VALUES_I ".
#define PI_VALUES_V { 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, NULL_ADDR, NULL_ADDR} //#define PI_VALUES_V {0.06f, 0.1f, 0.1f, 1.0f, -1.0f, 0.1f} // Kp, Ki, i10, Sat_max, Sat_min, Sat_storage float rk_V; // Reference value float yk_V; // Measured ADC signal float uk_V; // PI output //float lk_V; DCL_PI pi1 = PI_VALUES_V; float V_ref=100; int enable=0; // PI controller variables for current controller #define PI_VALUES_I { 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, NULL_ADDR, NULL_ADDR}
Thanking you,
Regards,
Vidhi
Dear Richard,
I try to see FPU registers and the value says "memory mapped".
I imported the one of the examples to see if it works with that. I flashed the code and it gives me the same error "#10263 and #10264". Now, I really don't get that how it finds two linker command file. Even your linker command file and other PCs gives me the same error.
Guide me further.
Thanking you !
Regards,
Vidhi