DrCoolZic wrote:Nyh wrote:DrCoolZic wrote:I choose a prescale of 200 wich gives a period of about 81µs and an overflow every 20 ms. As I get back to the timer in less than 20 ms I can test for overflow and proceed accordingly, but it would probably be better to setup an interupt handler on overflow, but I do not know (yet) how to write that in C.
It is possible to do that in Pure C but this is dark magic. You can only use code that doesn't change registers.
Code: Select all
void rte(void) 0x4E73;
volatile long int counter=0;
*(char*)0xfffa0fL=0xDF; /* clear interrupt mask */
Jdisint(13); /* disable timer A */
Xbtimer(0, 1, 128, handler); /* install and enable timer A handler */
Yes this is really dark magic! and extremely elegant solution compared to the code I wrote manipulating the timer registers, going in/out of sv mode ... !!!!
Lets see if I can make sense out of this:
void rte(void) 0x4E73;
I remember that you already mentioned this capability of Pure C to drop "Assembly opcode" inside C code. I have been looking everywhere in the Pure C help files but could not find any information on this ?
How did you found about this feature? What is the syntax?
I think it was in the Borland Turbo C manual, and I suppose it is also in the Pure C manual but I have to check that out.
DrCoolZic wrote: If I remember correctly you also gave examples passing an argument. Something like func(long value) 0x???? In that case the code dropped would be ???? folowed by value ? Is it limited to Only one argument or more ? What type of argument char, short, long ... ? This looke extremely powerful and I am interested by information even if it is not really portable.
It is a normal function call, so parameters are passed like in a normal function call, first 3 integers in D0, D1 and D2, first 2 addresses in A0 and A1, rest on the stack. With the opcodes you can manipulate all registers any way you like. So:
long asm_add(long x, long y) 0xD081;
will add D1 to D0 and because Pure C expects the result of a function in D0 you get the right result.
This way of inserting instructions is nice to do simple things. Most often I used to control the interrupt priority level with a:
void move_sr(int value) 0x46c0; /* move D0,SR */
For complex things it is far easier to write an assembly subroutine.
DrCoolZic wrote:So with a name like rte I guessed that the 0x4E73 is instruction for return from exception (probably another name for interrupt in 68k terminology - sorry I am more an x86 guy )
By the way I have dowloaded lots of documents on motorola (user's guide, ... ) but none of them have a simple table that list by hex value the associated opcode? So I can easely find that $4e73 is an RTE operation ??? Any pointer to such document ?
Well, my 68000 reference manual has just such a table. The book is called:
"68000. Deel 1: Anatomie van een super-microprocessor" by L. Nachtmann, published by Elektuur, 1e druk, 1986
I am afraid it is in Dutch. I have heavily used the book and it contains a lot of notes. In the end, before the instruction time tables is a table from hex code to instruction.
DrCoolZic wrote:The rest of the code is relatively clear but I have few questions:
First: in the handler you access register directly and use RTE. All this needs to be done in SV mode, so my guess is that the handler declare in Xbtimer is called in SV mode (humm this sound pretty obvious)
Not quite. The handler routine is jumped to when a timer A interrupt occurs. Then the 68000 is in Super mode.
DrCoolZic wrote:Second: You used Jdisint() ? This is suppose to disable interrupt ? I was rather expecting Jenabint() function to be called ? so that timer can generate interrupt ?
I think it is a good coding practice to disable an interrupt before you are going to change it. I am not 100% sure whether Xbtimer() disables the interrupt too. Anyway, better safe than sorry. Xbtimer() installs and starts an interrupt routine so there is no need to enable it with Jenabint().
DrCoolZic wrote:I noted the usage of volatile, so that if counter is used in some other places in the code it does not get "optimized".
With the volatile declaration you tell the compiler it cannot optimize the variable into a register. Usually you do this for variables that are changed outside the normal program flow, ie by an interrupt routine or hardware registers.