It is currently 19 Apr 2018 21:50

All times are UTC + 1 hour




Post new topic Reply to topic  [ 14 posts ] 
Author Message
 Post subject: reentracy trick
PostPosted: 24 Jan 2008 18:15 
Offline

Joined: 24 Jan 2008 17:50
Posts: 2
Hi,
I have found a trick to avoind reentrancy check of mikroC compiler.
It seems works

here is an example:

void Led(unsigned int cOn){
    PORTH.F3 = cOn;
}

void Led_Fake(unsigned int cOn){}

#pragma funcall Led_inter Led_Fake
// this pragma tell to MikroC that Led_inter will call
// only the function Led_Fake using indirect call (function pointers)

void Led_inter(unsigned int cOn){
    void (*pLed)(unsigned int cOn);
    pLed = &Led;
    pLed(cOn);
}

#pragma funcall Led_main Led
// this pragma tell to MikroC that Led_main will call
// only the function Led using indirect call (function pointers)

// So MikroC belive that the 2 functions will call different function
// and so thinks that there is not reentrancy

void Led_main(unsigned int cOn){
    unsigned char cSaveGIE;
    void (*pLed)(unsigned int cOn);

    cSaveGIE = INTCON.GIE;
    INTCON.GIE = 0;

    pLed = &Led;
    pLed(cOn);

    INTCON.GIE = cSaveGIE;
}

// Led_main call led using function pointer but do that disabling
// interrupts (and saving the state in order to restore at the end
// of the funtcion)
// This is important, because if during that function execution,
// an interrupt that executes LED starts through LED_INTER wrapper,
// there would be problems with local variables and parameters.
// In fact, these aren't allocated by compiler at runtime:
// they are statically allocated

// Now into interrupt you can use function Led
// calling the wrapper function Led_inter

void interrupt(void){
    Led_inter(0);
}

// And into main you can use function Led
// calling the wrapper function Led_main


void main(){
    Led_main(1);
}



I hope this will help.

Ronny

Epik srl
[url=http://www.epik.it]www.epik.it
[/url]


Top
 Profile  
 
 Post subject:
PostPosted: 02 Feb 2009 09:18 
Offline

Joined: 20 Jan 2009 07:33
Posts: 7
Hi..Thanks for the tip..
Just want to ask, does this dont have any constraints or limitations?


Top
 Profile  
 
 Post subject:
PostPosted: 02 Feb 2009 19:40 
Offline

Joined: 18 Jun 2008 11:43
Posts: 3751
Location: Nieuwpoort, Belgium
telknarf wrote:
Hi..Thanks for the tip..
Just want to ask, does this dont have any constraints or limitations?

Hi, some info on re-entry: http://www.ganssle.com/articles/begincornerent.htm :D

_________________
Kind regards,
Dany.
(happy user of mP PRO for PIC and dsPIC30/33 and PIC24, PicFlash2, RTClock, Max232 board, Ethernet PROTO board, MMC/SD Card Proto board, Yo2Lio's and Janni's libs)
http://www.rosseeld.be/DRO/PIC/index.htm


Top
 Profile  
 
 Post subject:
PostPosted: 04 Feb 2009 12:35 
Offline

Joined: 20 Jan 2009 07:33
Posts: 7
Hi Dany, thanks for the reply. Ill also try this one out.
By the way, you might have known this technique but for those who dont know this yet and met the same problem as mine, I also found another solution to this one and that is by having flags. By means of this, I dont need to put function calls to interrupts but instead have flags(or variables) within it and the function calls or actions for it will be done in the main loop. So, in this case, if there will be interrupts occuring in an instant, it will just set a value to my flags so that when the program exits the interrupt function, it will go back to the main loop, and when the program sees that the flag meets its condition(because the interrupt changes its value, thereby meeting the condition), the actions(or function calls) for that interrupt will occur or execute.


Top
 Profile  
 
 Post subject:
PostPosted: 04 Feb 2009 17:23 
Offline

Joined: 18 Jun 2008 11:43
Posts: 3751
Location: Nieuwpoort, Belgium
telknarf wrote:
By the way, you might have known this technique but for those who dont know this yet and met the same problem as mine, I also found another solution to this one and that is by having flags. By means of this, I dont need to put function calls to interrupts but instead have flags(or variables) within it and the function calls or actions for it will be done in the main loop. So, in this case, if there will be interrupts occuring in an instant, it will just set a value to my flags so that when the program exits the interrupt function, it will go back to the main loop, and when the program sees that the flag meets its condition(because the interrupt changes its value, thereby meeting the condition), the actions(or function calls) for that interrupt will occur or execute.
Nice! This is of course much better than calling the same routine in the main and the interrupt routine. :D :D

_________________
Kind regards,
Dany.
(happy user of mP PRO for PIC and dsPIC30/33 and PIC24, PicFlash2, RTClock, Max232 board, Ethernet PROTO board, MMC/SD Card Proto board, Yo2Lio's and Janni's libs)
http://www.rosseeld.be/DRO/PIC/index.htm


Top
 Profile  
 
 Post subject:
PostPosted: 15 May 2009 22:59 
Offline

Joined: 11 Mar 2005 18:26
Posts: 1093
Location: Aubenas, France
telknarf wrote:
Hi Dany, thanks for the reply. Ill also try this one out.
By the way, you might have known this technique but for those who dont know this yet and met the same problem as mine, I also found another solution to this one and that is by having flags. By means of this, I dont need to put function calls to interrupts but instead have flags(or variables) within it and the function calls or actions for it will be done in the main loop. So, in this case, if there will be interrupts occuring in an instant, it will just set a value to my flags so that when the program exits the interrupt function, it will go back to the main loop, and when the program sees that the flag meets its condition(because the interrupt changes its value, thereby meeting the condition), the actions(or function calls) for that interrupt will occur or execute.


Interesting point of view.
Can someone post small code to show the idea. (I'm not sure to understand correctly everything.

Thanks

_________________
Alain


Top
 Profile  
 
 Post subject:
PostPosted: 29 May 2009 12:14 
Offline

Joined: 11 Mar 2005 18:26
Posts: 1093
Location: Aubenas, France
telknarf wrote:
Hi Dany, thanks for the reply. Ill also try this one out.
By the way, you might have known this technique but for those who dont know this yet and met the same problem as mine, I also found another solution to this one and that is by having flags. By means of this, I dont need to put function calls to interrupts but instead have flags(or variables) within it and the function calls or actions for it will be done in the main loop. So, in this case, if there will be interrupts occuring in an instant, it will just set a value to my flags so that when the program exits the interrupt function, it will go back to the main loop, and when the program sees that the flag meets its condition(because the interrupt changes its value, thereby meeting the condition), the actions(or function calls) for that interrupt will occur or execute.


Hi,

just ten lines of example to show the idea would be nice.

Thanks

_________________
Alain


Top
 Profile  
 
 Post subject:
PostPosted: 03 Jun 2009 19:10 
Offline

Joined: 14 Feb 2008 20:35
Posts: 82
Location: The Earth
The above example shows a way to create a #pragma entry in the mcu Defs file (re-creation of a library). It is a great idea, but what about recreating the built-in functions such as VDelay? I need to re-create the VDelay function to avoid the re-entrancy error. Any idea? Thanks.


Top
 Profile  
 
PostPosted: 10 May 2010 14:35 
Offline

Joined: 14 Mar 2010 08:35
Posts: 115
Hi,ronnym.I also have reentrancy problem in my program.My compiler
mikroC PRO V2.50,give me these error messages;


184 365 Reentrancy is not allowed: function [color=#000000]'Lcd_Out'
called from two threads __Lib_Lcd.c
184 365 Reentrancy is not allowed: function 'Lcd_Out' called from two threads __Lib_Lcd.c
50 365 Reentrancy is not allowed: function 'Lcd_Chr_CP' called from two threads __Lib_Lcd.c
18 365 Reentrancy is not allowed: function 'Lcd_Cmd' called from two threads __Lib_Lcd.c
0 102 Finished (with errors): 10 May 2010, 17:39:42 t4x.mcppi[/color]

I read your trick but I do not know how I must modified and used that for my program.
Would you please help me to apply and write that?

Here are my code firmware and program;

       
#define stepsize  98
int  t4=0,index;
char *tc;
int  adcvalmax[8];
int  interb0=0;

void Display_AdcX(int adcvalmax[8] ) {
   int i=0,m=0;
   char ch[8];
 extern int adcvalmax[8];// 16 1504 Initialization of extern object 'adcvalmax' t1x.c //
   memset(adcvalmax,0,8*sizeof(int));
   memset(ch,0,8*sizeof(int));

  for(i,m=0;i,m<8;i++,m++){ //IS THIS FOR STATEMENT RIGHT? ****************

  ch[i] = adcvalmax[m] /1000; //prepare value for display in A
  Lcd_Chr(2, 1, 48 + ch[i]); //write ASCII at 2nd row,1st column
  Lcd_Chr_Cp('.');

  ch[i]    = (adcvalmax[m] /100) % 10;
  Lcd_Chr_Cp(48 + ch[i]);

  ch[i]   = (adcvalmax[m] /10) % 10;
  Lcd_Chr_Cp(48 + ch[i]);

  ch[i]    = adcvalmax[m] % 10;
  Lcd_Chr_Cp(48 + ch[i]);
  Lcd_Chr_Cp('A');

  }

}//~


void MR_CHNS(int adcvalmax[8]){

    long longadc=0;
  extern int adcvalmax[8];// 43 1504 Initialization of extern object 'adcvalmax' t1x.c//
    int ch[8];//declares a array of 8 integers
    int m=0,i=0;
    int Px=0,P1st=0,P2nd=0;

    memset(adcvalmax,0,8*sizeof(int));
    memset(ch,0,8*sizeof(int));

  for(i=0;i<8;i++){

     for(m=0;m<8;m++){

       do{
          ch[i]=ADC_Read(i);
          Px=ch[i];
         }while(Px!=0);

      P1st=ADC_Read(m);
      Delay_ms(10);//10 ms pause
      P2nd=ADC_Read(m);

       while(P1st<=P2nd){
            P1st=P2nd;
            P2nd=0;
         P2nd=ADC_Read(m);
       }

   adcvalmax[m] = P1st;// if (vf>vn)
   index = (stepsize);
   ADRESH = (ADRESH)&&(0b00000011);
   longadc = ADRESH + ADRESL;
   adcvalmax[m] = longadc * index;//in mA or mv

     }
  }

}//~



void update_pwm(unsigned short int rp2val){
    rp2val=0;

    t4  = Adc_Read(4);
    rp2val = ADRESL;


    PWM1_Set_Duty(rp2val);//Set & change duty ratio due to the VRP2 value
                                                         //from 0 -255;(ADRESL)


    LCD_Out(2,14,&rp2val);// 96 1508 Implicit conversion of int to ptr t1x.c //

                //(127: 50% duty ratio)
    if(rp2val == 127) PORTC.F5=1;//Turn the LED on (RC5/pin24)

}//~



void interrupt() {

  static int interb0;
                            //Turn off charger interrupt via INTO/RB0
  INTCON.INT0IF=0;//Clear INT0(INTCON)external interrupt Flag bit to detect
                                                                 //next inter.
  interb0++;//interb0 = interb0+1

  while(interb0 ==1){

    PWM1_Stop();//Stop PWM


  LCD_Cmd(_LCD_CLEAR);// send command  to LCD (clear LCD)
  tc = "STAND BY!";// assign a text to string
  LCD_Out(1,1,tc);// print a string  on LCD, 1st row, 1st column

    PORTC.F3=1;//Turn the LED on (RC3/pin18):LED stand by state indicator
    Delay_ms(1000);//One second pause
    PORTC.F3=0;//Turn the LED off (RC3/pin18)
   }

 if(interb0!=1){
  PWM1_Start();//Start PWM ,(interb0!=1)
  interb0 = 0;
  PORTC.F3=0;//Turn the LED off (RC3/pin18)
  }

}//~


// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections


void main() {

  PORTA=0;//Clear port A
  TRISA=0XFF;//Port A is input
  PORTD=0;//Clear port D
  TRISD=0;//Port D is output
  PORTC=0;//Clear port C
  TRISC=0;//port C is output
  PORTB=0;//Clear port B
  TRISB=0XFF;//port B is input
  PORTE=0;//Clear port E
  TRISE=0XFF;//Port E is input
  TRISC = PORTC = 0;

  INTCON.GIEH = 1; // When IPEN = 1,enables all high priority interrupts
  INTCON.GIEL=1;//When IPEN = 1,enables all low priority peripheral interrupts
  RCON.IPEN = 1;//Enable priority levels on interrupts
  INTCON.INT0IE=1;//Enables the INT0 external interrupt
  INTCON2.INTEDG0 = 0;// Interrupt on falling edge


  LCD_Init();// initialize(4-bit interface connection)
  LCD_Cmd(_LCD_CURSOR_OFF);// send command to LCD (cursor off)
  LCD_Cmd(_LCD_CLEAR);// send command  to LCD (clear LCD)
  tc = "Hi!";// assign a text to string
  LCD_Out(1,1,tc);// print a string  on LCD, 1st row, 1st column



  PWM1_Init(500);//500HZ but should Initialize PWM module at 50HZ ;
                                //using frequency divider with D-Flip_Flop IC.
  PWM1_Set_Duty(127);//Set duty ratio to 50%



  update_pwm(t4);
  PWM1_Start();//Start PWM


  //Not required to determine ADCON0;it is asked by uC compiler on NEW Project
  // icon bar at the top at first automatically &done via:Adc_Read() Library

  ADCON1=0x80;//configure VDD=Vref+,Vss=Vref-,8-analog channels&Right justified
                                                           //A/D Result Format
  Delay_ms(2000);


  MR_CHNS(adcvalmax);
  Display_AdcX(adcvalmax);



  }//~!






              0 1 mikroCPIC1618.exe -MSF -DBG -pP18F452 -DL -O11111114 -fo8 -N"E:\XT1\t4x.mcppi" -SP"E:\Bob's File\mikroC PRO PIC 2009 V2.50\MikroCProV2.50\defs\" -SP"E:\Bob's File\mikroC PRO PIC 2009 V2.50\MikroCProV2.50\uses\P18\" -SP"E:\XT1\" "t4x.c" "__Lib_Math.mcl" "__Lib_MathDouble.mcl" "__Lib_System.mcl" "__Lib_Delays.mcl" "__Lib_CType.mcl" "__Lib_CString.mcl" "__Lib_CStdlib.mcl" "__Lib_CMath.mcl" "__Lib_Conversions.mcl" "__Lib_Sprintf.mcl" "__Lib_PrintOut.mcl" "__Lib_Sprinti.mcl" "__Lib_Sprintl.mcl" "__Lib_Time.mcl" "__Lib_Trigonometry.mcl" "__Lib_Button.mcl" "__Lib_Keypad4x4.mcl" "__Lib_Manchester.mcl" "__Lib_OneWire.mcl" "__Lib_PS2.mcl" "__Lib_Sound.mcl" "__Lib_SoftI2C.mcl" "__Lib_SoftSPI.mcl" "__Lib_SoftUART.mcl" "__Lib_ADC_A_C.mcl" "__Lib_EEPROM_256.mcl" "__Lib_FLASH_w8_e64.mcl" "__Lib_I2C_c34.mcl" "__Lib_PWM_c21.mcl" "__Lib_SPI_c345.mcl" "__Lib_UART_c67.mcl" "__Lib_PortExpander.mcl" "__Lib_CANSPI.mcl" "__Lib_CF.mcl" "__Lib_CFFat16.mcl" "__Lib_GlcdFonts.mcl" "__Lib_Glcd.mcl" "__Lib_LcdConsts.mcl" "__Lib_Lcd.mcl" "__Lib_Mmc.mcl" "__Lib_MmcFat16.mcl" "__Lib_RS485.mcl" "__Lib_T6963C.mcl" "__Lib_SPIGlcd.mcl" "__Lib_SPILcd.mcl" "__Lib_SPILcd8.mcl" "__Lib_SPIT6963C.mcl" "__Lib_EthEnc28j60.mcl" 
0 125 All files Preprocessed in 15 ms 
0 121 Compilation Started t4x.c
223 122 Compiled Successfully t4x.c
0 126 All files Compiled in 157 ms 
184 365 Reentrancy is not allowed: function 'Lcd_Out' called from two threads __Lib_Lcd.c
184 365 Reentrancy is not allowed: function 'Lcd_Out' called from two threads __Lib_Lcd.c
50 365 Reentrancy is not allowed: function 'Lcd_Chr_CP' called from two threads __Lib_Lcd.c
18 365 Reentrancy is not allowed: function 'Lcd_Cmd' called from two threads __Lib_Lcd.c
0 102 Finished (with errors): 10 May 2010, 17:39:42 t4x.mcppi





Thanks & Regards,












ronnym wrote:
Hi,
I have found a trick to avoind reentrancy check of mikroC compiler.
It seems works

here is an example:

void Led(unsigned int cOn){
    PORTH.F3 = cOn;
}

void Led_Fake(unsigned int cOn){}

#pragma funcall Led_inter Led_Fake
// this pragma tell to MikroC that Led_inter will call
// only the function Led_Fake using indirect call (function pointers)

void Led_inter(unsigned int cOn){
    void (*pLed)(unsigned int cOn);
    pLed = &Led;
    pLed(cOn);
}

#pragma funcall Led_main Led
// this pragma tell to MikroC that Led_main will call
// only the function Led using indirect call (function pointers)

// So MikroC belive that the 2 functions will call different function
// and so thinks that there is not reentrancy

void Led_main(unsigned int cOn){
    unsigned char cSaveGIE;
    void (*pLed)(unsigned int cOn);

    cSaveGIE = INTCON.GIE;
    INTCON.GIE = 0;

    pLed = &Led;
    pLed(cOn);

    INTCON.GIE = cSaveGIE;
}

// Led_main call led using function pointer but do that disabling
// interrupts (and saving the state in order to restore at the end
// of the funtcion)
// This is important, because if during that function execution,
// an interrupt that executes LED starts through LED_INTER wrapper,
// there would be problems with local variables and parameters.
// In fact, these aren't allocated by compiler at runtime:
// they are statically allocated

// Now into interrupt you can use function Led
// calling the wrapper function Led_inter

void interrupt(void){
    Led_inter(0);
}

// And into main you can use function Led
// calling the wrapper function Led_main


void main(){
    Led_main(1);
}



I hope this will help.

Ronny

Epik srl
[url=http://www.epik.it]www.epik.it
[/url]


Top
 Profile  
 
 Post subject: Re: reentracy trick
PostPosted: 21 May 2011 12:28 
Offline

Joined: 20 May 2011 20:01
Posts: 2
Hey, i am making a system , the where MCU (PIC18F452) continously reads data from GPS via Soft_UART, and whenever an interrupt on UART1 Rx pin occurs, it starts reading data from UART1. the thing is, how can i avoid reentrancy errors ? Since im totally new in this field, can you please help me out in modifying my code? also is there an option i can disable the interrupt just before calling the re entrant function in main() ? PLease HELP
void interrupt() {
/*if(timer==1)
  {cnt++;}               // Increment value of cnt on every interrupt
  TMR0L  = 96;
  INTCON = 0x20;       // Set T0IE, clear T0IF*/
   if (PIR1.RCIF)
   {
  if(UART1_Data_Ready())
{
UART1_Read_Text(junk,"\r\n",255);
//Lcd_Chr_Cp('a');
UART1_Read_Text(header, "\r\n",255);
//Lcd_Chr_Cp('b');
UART1_Read_Text(message, "\r\n",255);
//Lcd_Chr_Cp('c');
Lcd_Out(2,12,header);
 Lcd_Out(3,12,message);
 if(header[0]=='+' && header[1]=='C' && header[2]=='M' && header[3]=='T')
 {
 Lcd_Out(1,10,"new message");
 new_message=1;
 }
 else
     {
     new_message=0;
     }
 }
 }
}

void main()
{
Lcd_Init();
Lcd_Cmd(_Lcd_CLEAR);
Lcd_Cmd(_Lcd_CURSOR_OFF);

i=Soft_UART_Init(&PORTC, 4,5,4800,0);
UART1_Init(9600);
UART1_Write_Text("AT+cmgf=1");
delay_ms(1000);
UART1_Write(13);
while(!UART1_Data_Ready())
{}
if(UART1_Data_Ready())
{

UART1_Read_Text(junk,"OK\r\n",255);

}


UART1_Write_Text("AT+ cnmi=0,2,2,1");
delay_ms(1000);
UART1_Write(13);
while(!UART1_Data_Ready())
{}
if(UART1_Data_Ready())
{
UART1_Read_Text(junk,"OK\r\n",255);
}
cnt = 0;              // Initialize cnt
 INTCON.GIE = 1;
INTCON.PEIE = 1;
PIE1.RCIE = 1; //enable interrupt.
TRISD.f2=1;
TRISD.f3=1;
PORTD=0x00;
while(1)
{
 while(!UART1_Data_Ready())   //read from GPS
 {
//process this data }

}
}




Top
 Profile  
 
 Post subject: Re: reentracy trick
PostPosted: 23 May 2011 09:18 
Offline
mikroElektronika team
User avatar

Joined: 25 Jan 2008 09:56
Posts: 9692
Hi,

I believe I have answered you on the Support desk.

Regards,
Filip.


Top
 Profile  
 
 Post subject: Re: reentracy trick
PostPosted: 12 Jul 2012 15:34 
Offline

Joined: 09 Jul 2012 05:22
Posts: 4
Hi,

Thanks for posting this trick.
I found that this trick can be further simplified.
void LED_ON(int c){
     RD0_bit=1;
}

#pragma funcall interrupt

void interrupt(){
     void(*pFun)(int c);
     pFun=&LED_ON;
     pFun(1);
}

void main() {
     void(*pFun)(int c);
     pFun=&LED_ON;
     
     TRISD=0;
     PORTD=0;
     
     pFun(1);
     
     while(1);
}


Tested on Pro V5.61.


Top
 Profile  
 
 Post subject: Re: reentracy trick
PostPosted: 13 Jul 2012 13:25 
Offline

Joined: 18 Feb 2006 13:17
Posts: 4891
Yes, it works with last versions of mC. Don't think it worked while ronnym posted his trick, though.

Anyway, while it's possible to force full reentrancy (with all it's risks), it's in some cases impossible to convince compiler that there's no reentrancy when there in fact isn't. Pragma funcall works kind of in reverse. Easily accepts false information while rejecting a true one.

_________________
Replacement libraries for mP PRO and PIC18 processors, mP PRO tips & trics


Top
 Profile  
 
 Post subject: Re: reentracy trick
PostPosted: 05 Feb 2015 16:30 
Offline

Joined: 27 Dec 2014 09:28
Posts: 7
cclinus wrote:
Hi,

Thanks for posting this trick.
I found that this trick can be further simplified.
void LED_ON(int c){
     RD0_bit=1;
}

#pragma funcall interrupt

void interrupt(){
     void(*pFun)(int c);
     pFun=&LED_ON;
     pFun(1);
}

void main() {
     void(*pFun)(int c);
     pFun=&LED_ON;
     
     TRISD=0;
     PORTD=0;
     
     pFun(1);
     
     while(1);
}


Tested on Pro V5.61.


will this work on library funtions such as atoi???


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 14 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: