CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

movf - Expecting an opcode mnemonic (WOAH!!!!)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

movf - Expecting an opcode mnemonic (WOAH!!!!)
PostPosted: Wed Aug 18, 2004 7:35 am     Reply with quote

The code below, should be fine when I try to compile it I get the following Neuromancer/Blade Runner Error
Quote:
Expecting an opcode mnemonic

Cool COOL ERROR Cool

For us thickies what does it mean I can compile the code if I remove the line MOVF PORTE,0,0

Anybody any clues


Nice




Code:
#define Fosc 40000000                 // I'm using a 40 MHz crystal
#include <18F8621.h>
//-------------------------------------------------------------------------------------
// COMPILER DIRECTIVES and HARDWARE CONFIGURATION
#use delay(clock = Fosc)

#fuses EC_IO
#fuses NOOSCSEN   // Oscillator System Clock Switch Disabled
#fuses NODEBUG   // No Background Debugger
#fuses NOLVP      // Low Voltage ICSP Disabled
#fuses NOPROTECT    // No Code Protect
#fuses NOWDT      // No onboard watchdog
#fuses PUT         // Power Up Timer Enabled
#fuses BROWNOUT   // Brown Out Reset enabled
#fuses WRT
#fuses STVREN

#define PORTE 0xF84
#define PORTH 0xF87

//-------------------------------------------------------------------------------------
// GLOBALS - GENERAL
static short change = 0;    //State Switch for watchdog
int oldE;
//-------------------------------------------------------------------------------------
// FUNCTION PROTOTYPES - GENERAL
void setupMain(void);
void asmRoutine(void);
//-------------------------------------------------------------------------------------
// MAIN
void main()
{
   setupMain();
   while (1)
    {
      asmRoutine();
      if (change)
      {

      }      
      }
}
//-------------------------------------------------------------------------------------
// MAIN SETUP
void setupMain(void)
{
   oldE = input_e();
}
//-------------------------------------------------------------------------------------
// MAIN ASM ROUTINE
void asmRoutine(void)
{
#asm
MOVF PORTE,0,0
BCF change
CPFSEQ oldE
BSF change
BTG PORTH,0
#endasm   
}
valemike
Guest







PostPosted: Wed Aug 18, 2004 7:40 am     Reply with quote

I haven't touched PIC assembly since 1998, but i thought the MOVF command can only have 2 arguments. Thus porte,0,0 is wrong, isn't it?

needs to be:
movf porte,0
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Wed Aug 18, 2004 7:48 am     Reply with quote

on the 18F8621
the last 0 is about using the 256byte access bank
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Wed Aug 18, 2004 8:19 am     Reply with quote

In listings it is shown like this

MOVF FC2,W

Try searching the forum for examples of syntax.
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Aug 18, 2004 8:34 am     Reply with quote

Just a comment. You just spent some money buying the cross Compiler, let the compiler to do his job.
It isn�t a good practice to "mix" Assembler and C, unless you really need a very short routine
that justify that. Do it in C and use the Assembler to check the generated output .lst file

Best wishes,

Humberto
Ttelmah
Guest







PostPosted: Wed Aug 18, 2004 8:45 am     Reply with quote

homfray wrote:
on the 18F8621
the last 0 is about using the 256byte access bank

Unfortunately, the assembler with CCS, is not the normal assembler. Functions that go beyond the older syntax, are often a long time coming (for instance, RETFIE, did not accept the '0' or '1' for several dozen compiler versions in the early days of the 18family). Even worse, the assembler that is generated by the compiler, itself won't be accepted by the internal assembler.

I'm afraid you are going to have to contact CCS, and wait for a few versions, when they will (with any luck), implement the feature.
The alternative (which is what I used in a similar position), is to 'bodge' round the problem, by using the older syntax, then using a #rom statement, to place the required byte value at the required location.

However it is also important to understand that the instruction syntax, is slightly different from the normal assembler, in that you don't have to load the BSR yourself. So if (for instance), you code 'MOVF PORTE,0', the compiler itself, decides whether the BSR needs to be loaded, and does so, and on recent version, appears to know about the access bank. Hence there is not the normal 'one inctruction per line' relationship between the assembler and the final code, and also some features that would interfere with the compilers ability to optimise, are deliberately left out. This may well be one

Best Wishes
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Wed Aug 18, 2004 8:55 am     Reply with quote

I have built some electronics which looks at a couple of ports and compares them to a previous reading and if there is a difference it writes them internally. I would like run this loop every 5-10us and as I have not managed to get anywhere close to this time (I am running 40MHz EC) I am trying to see if I can write it in asm to see if it can work any quicker, It appears it is imposible to uss a CCS RTCC interrupt and time anything in the order of 10us.

I have heard you can use priority interrupts and write your own handler but I have searched this forum high and low and have found nothing.

If anyine knows any code or any other way where I can

I have tried the following code and I don't even ge a constant time let alone a constant fast time??

Code:
#define Fosc 40000000                 // I'm using a 40 MHz crystal
#include <18F8621.h>
//-------------------------------------------------------------------------------------
// COMPILER DIRECTIVES and HARDWARE CONFIGURATION
#use delay(clock = Fosc)

#fuses EC_IO
#fuses NOOSCSEN   // Oscillator System Clock Switch Disabled
#fuses NODEBUG   // No Background Debugger
#fuses NOLVP      // Low Voltage ICSP Disabled
#fuses NOPROTECT    // No Code Protect
#fuses NOWDT      // No onboard watchdog
#fuses PUT         // Power Up Timer Enabled
#fuses BROWNOUT   // Brown Out Reset enabled
#fuses WRT
#fuses STVREN

#byte OSCCON = 0xFD3
#byte T1CON = 0xFCD
//-------------------------------------------------------------------------------------
// GLOBALS - GENERAL
static short state = 0;    //State Switch for watchdog
long i;
long us,ms,s;
int dataPoint1[700];
long dataPoint2[700];
long dataPoint3[700];
long dataPoint5[700];
int valueOfE, oldValueOfE, valueOfF, oldValueOfF;
//-------------------------------------------------------------------------------------
// FUNCTION PROTOTYPES - GENERAL
void setupMain(void);
//-------------------------------------------------------------------------------------
// INTERRUPTS - TIME 0.5ms
#int_rtcc
void int_rtcc_isr(void)
{
   set_timer0(65475);      
   state=~state;
}
//-------------------------------------------------------------------------------------
// MAIN
void main()
{
   setupMain();
   while (1)
    {
      valueOfE=input_e();
      valueOfF=input_f()& 0b011111111;
   
      dataPoint1[i]=valueOfE;
      dataPoint2[i]=valueOfF;
      dataPoint3[i]=s;
      dataPoint5[i]=us;

      if(valueOfE != oldValueOfE || valueOfF != oldValueOfF && i < 700)   
      if(valueOfE != oldValueOfE && i < 700)      
         i++;         
      
      oldValueOfE = valueOfE;
      oldValueOfF = valueOfF;
 
      output_bit(PIN_H0,state);   
      state=~state;
      
      us++;
      if (us==10000)
      {
         s++;
         us=0;
      }
      
      }
}
//-------------------------------------------------------------------------------------
// MAIN SETUP
void setupMain(void)
{
   setup_counters(RTCC_INTERNAL, RTCC_DIV_1);
   set_timer0(65475);                   // set timer for 0.5ms
      enable_interrupts(GLOBAL);         // set global interrupts
      enable_interrupts(INT_RTCC);        // disable timer interupt

   oldValueOfE = input_e();
   oldValueOfF = input_f() & 0b011111111;
   us=0;
   s=0;
   i=0;
}
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Wed Aug 18, 2004 9:01 am     Reply with quote

you are quite correct Ttelmah, when you get rid of that last 0 it works. Am I correct that you have doone some work on writing your own high speed handler/interrupts, have you any example code I could look at

Nice!!
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 18, 2004 9:23 am     Reply with quote

What else has to be done? A lot depends on what all you are trying to do, how fast can you service the main loop, does this have to be every 5-10us or maybe monitor it for a while and then do some stuff and then come back and monitor it again, ect..
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Aug 18, 2004 12:02 pm     Reply with quote

Quote:
I have tried the following code and I don't even ge a constant time let alone a constant fast time??
Where do you expect to get a contstant time? What are you measuring? In the following text I assume you are meassuring the RTCC interrupt routine.

You are setting the timer to 0,5ms with:
Code:
// INTERRUPTS - TIME 0.5ms
#int_rtcc
void int_rtcc_isr(void)
{
   set_timer0(65475);     
   state=~state;
}
First of all, I think you are setting the wrong value for timer0. It won't overflow in 0,5ms but in 65536 - 65475 = 61 instruction cycles = 6,1 us.

Code:
      if(valueOfE != oldValueOfE || valueOfF != oldValueOfF && i < 700)   
      if(valueOfE != oldValueOfE && i < 700)     
         i++;         
This doesn't make sense. You probably want to delete the first line?

Quote:
I have heard you can use priority interrupts and write your own handler but I have searched this forum high and low and have found nothing.
Search deeper. Use keywords like 'interrupt' and 'FAST' and you will find many hits.

Quote:
I would like run this loop every 5-10us
This is very fast! 50 - 100 instruction cycles!!!
For this kind of speeds forget about interrupts. An interrupt has overhead for saving and restoring context, you don't want to do this. Much faster is to wait in your main loop for the timer interrupt flag being set and then execute the rest of your loop.

Another improvement is to use timer2 i.s.o. timer0. Timer2 has the advantage of having a comparator so you can save some overhead by setting the repeat frequency only once.

Code:
#BIT TMR2IF=0x0F9E.1
int8 delay_in_us = 10;    // Execute loop every 10us
void main()
{
  setupMain();
  while (1)
  {
    // Wait for Timer_interrupt_flag
    while (! TMR2IF)
      ;  // wait
    clear_interrupt(INT_TIMER2);

    // rest of your code here
  }
}
//-------------------------------------------------------------------------------------
// MAIN SETUP
void setupMain(void)
{
    setup_timer_2(T2_DIV_BY_1, delay_in_us, 10)
    clear_interrupt(INT_TIMER2);
    disable_interrupts(GLOBAL);         // disable all interrupts

   oldValueOfE = input_e();
   oldValueOfF = input_f() & 0b011111111;
   us=0;
   s=0;
   i=0;
}
Ttelmah
Guest







PostPosted: Wed Aug 18, 2004 2:51 pm     Reply with quote

homfray wrote:
you are quite correct Ttelmah, when you get rid of that last 0 it works. Am I correct that you have doone some work on writing your own high speed handler/interrupts, have you any example code I could look at

Nice!!

The thread seems to have got into an interesting 'timeloop', with older threads interleaved, when I view it.
Yes, I have done quite a bit of work on my own interrupts. There are a series of different approaches that work. The first is handling a single high speed interrupt is relatively each. You can then use the 'fast' keyword, and provided you keep the code simple (linear, with no table calls - so no switch statements without a 'default', and no array accesses, and no arithmetic beyond simple integer addition/subtraction), you can then use the 'retfie 1' ability to give a very 'brisk' handler. Beyond this, you can, if you restrict the registers that need to be saved in a similar way, you can also abridge the code needed in a normal handler as well.
I have posted both a simple fast handler, and a fairly complex 'int global' handler as well in the past, and they should be in the old archive. The CCS assembler documentation is appalling. It uses a different syntax, yet details of this are not reported till you 'quiz' them. There are also some significant 'oddities' about the handling of the fast interrupt, and limitations in this area, that have been discussed in the past in the new forum, and a bit of research should find the threads.

Best Wishes
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Thu Aug 19, 2004 2:40 am     Reply with quote

Code:
  if(valueOfE != oldValueOfE || valueOfF != oldValueOfF && i < 700)   
      if(valueOfE != oldValueOfE && i < 700)


Sorry ckielstra normally comment one of these lines out to check speed issues. I will have a play with timer2 and report back if I get some success. Cheers for the example I will have a play.

I would rather leave the asm code to others if possible so if there is a fix where I can carry on using C that is grand!!!

Ttelmah, cheers I will take a look in the archive for 'simple fast handler' and ' 'int global' handler'

Cheers guys
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Thu Aug 19, 2004 3:56 am     Reply with quote

Code:
clear_interrupt(INT_TIMER2);


How do I implement this as it is not a function asI only have PCH v3.180.

I should probably sort it out and buy the upgrade!!
_________________
Nice!!!
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Aug 19, 2004 5:21 am     Reply with quote

It's very easy to clear the interrupt with the already given definition of TMR2IF.

Code:
clear_interrupt(INT_TIMER2);

Is equal to:

#BIT TMR2IF=0x0F9E.1
TMR2IF = 0;
homfray



Joined: 19 Nov 2003
Posts: 45
Location: Oxford

View user's profile Send private message Visit poster's website

PostPosted: Thu Aug 19, 2004 7:11 am     Reply with quote

Thanks ckielstra

just to confirm in the code you wrote previously

Code:
#BIT TMR2IF=0x0F9E.1
int8 delay_in_us = 10;    // Execute loop every 10us
void main()
{
  setupMain();
  while (1)
  {
    // Wait for Timer_interrupt_flag
    while (! TMR2IF)
      ;  // wait
    clear_interrupt(INT_TIMER2);

    // rest of your code here
  }
}
//-------------------------------------------------------------------------------------
// MAIN SETUP
void setupMain(void)
{
    setup_timer_2(T2_DIV_BY_1, delay_in_us, 10)
    clear_interrupt(INT_TIMER2);
    disable_interrupts(GLOBAL);         // disable all interrupts

   oldValueOfE = input_e();
   oldValueOfF = input_f() & 0b011111111;
   us=0;
   s=0;
   i=0;
}


I could actually change it to

Code:
#BIT TMR2IF=0x0F9E.1
int8 delay_in_us = 10;    // Execute loop every 10us
void main()
{
  setupMain();
  while (1)
  {
    // Wait for Timer_interrupt_flag
    while (! TMR2IF)
      ;  // wait
  TMR2IF = 0; //INSTEAD OF: clear_interrupt(INT_TIMER2);

    // rest of your code here
  }
}
//-------------------------------------------------------------------------------------
// MAIN SETUP
void setupMain(void)
{
    setup_timer_2(T2_DIV_BY_1, delay_in_us, 10)
    TMR2IF = 0;  //INSTEAD OF: clear_interrupt(INT_TIMER2);
    disable_interrupts(GLOBAL);         // disable all interrupts

   oldValueOfE = input_e();
   oldValueOfF = input_f() & 0b011111111;
   us=0;
   s=0;
   i=0;
}


Would I be correct in thinking that clear_interrupt is in newer versions of the compiler?

Once again, thanks
_________________
Nice!!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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 vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group