6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 14, 2024 5:02 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Thu Aug 08, 2019 8:46 pm 
Offline

Joined: Thu Aug 08, 2019 7:52 pm
Posts: 4
Hello,

A few days ago I downloaded the wdctools package to try out the c-compiler for the 65816. I know that most people seem to prefer assembly for this CPU, but that is just a bridge to far for me. Also I have to port some existing c-code and even that is outside my normal comfort zone as I mostly work with the more "modern" high level languages in my day to day :oops: .

I more or less got my "hello world" sample to run in the simulator. Now I want to get the interrupts to work, but between the "not so great" manual and my limited c experience I'm running into problems I do not understand. Hopefully someone here knows how this tool-set works and give me some assistance.

I created this simple C-file. It has a counter loop so I can see something happening in memory while simulating. The IRQ section is straight from the manual, I only added a tab before both assembly lines to prevent another error from the compiler. I guess the manual is wrong there to... :shock:
Code:
int far Int_happened = 0;
int far counter = 0;
int far dummy = 0;

interrupt void IRQHandler(void)             
{             
   Int_happened = 1;             
}       
#asm
   org $ffee     ; 65816 IRQ vector             
   dw   ~~IRQHandler             
#endasm


void main(void) {
   
   // Infinite loop
   while(1) {
      counter++;
      dummy = counter;
      if (dummy == 200)
         dummy = 0;
   }
}



If I comment out the #asm -#endasm section it compiles fine and runs in the simulator using:
wdc816cc -ML simple.c -bs
wdcln -HZ -G -V -T -P00 simple.obj c0l.obj -LCL -O simple.bin
wdcdb simple.bin
The manual says the raw asm startup code from c0l.obj should be available in the tools package but only the object file is in the lib folder. I tried to contact support but no response so far.

Does anybody here know how to help me define the interrupt routine properly using the wdc startup code for the large memory model?

Must be something simple I'm missing, but I cannot seem to figure it out at the moment.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 09, 2019 1:46 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
In the #asm section, the ORG is an assembler directive, which I think should appear at the beginning of the line, not indented. The DW should indeed be indented as shown.

I would also move the #asm section to the very end of the file, to avoid nasty interactions between the ORG directive and the compiler's own code generation. You can move the interrupt handler itself as well, if you want to keep the code together.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 09, 2019 6:24 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Welcome, bzuidgeest!

Your interrupt handler will need to end with an RTI, I would think, not the usual RTS. I don't know how you are supposed to do that with this toolchain, but possibly an #asm section before the closing brace of the handler routine would do it.
Code:
interrupt void IRQHandler(void)             
{             
   Int_happened = 1;             
#asm
   rti
#endasm
}


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 09, 2019 7:16 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I suspect that the "interrupt" keyword in front of the handler's definition does precisely that.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 09, 2019 7:18 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Aha! I missed that...


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 09, 2019 7:49 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
Don't try to set the vector in your code, remove this:
Code:
#asm
   org $ffee     ; 65816 IRQ vector             
   dw   ~~IRQHandler             
#endasm

The startup module provides a native mode IRQ handler that pushes essential registers and then calls IRQHandler. The compiler has an 'interrupt' keyword but I don't think it does anything -- the calling code uses the same JSR/JSL instruction sequence as a C standard function (depending on memory model).

Your handler won't be called unless you have configured a peripheral to generate them and enabled interripts (CLI).

I requested a copy of the startup code myself this week for something I'm working on and have recieved a copy. Most of it is shown in the assembler/linker manual but there are some extra bits in the real source (like the shadow vectors table in the 816SXB).

My petty annoyance of the week was the provision of the C header for setjmp/longjmp but no implementation of the functions in the library. Fiddly but now coded. Also the strcpy (and probably other functions) have a 64K limit (even in >64K data memory models) which is not documented.

I'm working on header and library for the 265SXB which I will share when its ready.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
PostPosted: Sun Aug 11, 2019 6:53 pm 
Offline

Joined: Thu Aug 08, 2019 7:52 pm
Posts: 4
Thank you all for your answers.

As far as I have determined in the past days the compiler generates code for interrupts if a function declaration starts with interrupt. It pushes some values and ends the function with an RTI. When I set the compiler to output assembly I can confirm this happens.
I still have not received a copy of the startup code, but if BitWise is to be believed (and I see no reason why to, as he did receive it :D ) I should be able to get it working by removing the interrupt qualifier and removing the attempt to set the vector myself. Then the interrupt handler in the startup code should call my function. I guess the interrupt qualifier is for when you write your own startup code. I really wish the manual was more clear on these things.

@Bitwise
I also noticed the missing setjmp/longjmp implementation. This is noted in the manual as incomplete. Fixing that is beyond my capability at the moment, so if you could post your work when finished that would be great. And last could you PM me a copy of the startup code? That removes at least one black box. If you cannot for whatever reason, that OK, I'll just keep pestering them myself for it :D

Oh, btw the target for me is the c256 foenix board. c256foenix.com. For those interested.


Top
 Profile  
Reply with quote  
PostPosted: Sun Aug 11, 2019 7:26 pm 
Offline

Joined: Thu Aug 08, 2019 7:52 pm
Posts: 4
As per BitWise his comment, the example code in my first post should have been:

Code:
int far Int_happened = 0;
int far counter = 0;
int far dummy = 0;

void IRQHandler(void)             
{             
   Int_happened = 1;             
}       

void main(void) {
  asm cli;

   // Infinite loop
   while(1) {
      counter++;
      dummy = counter;
      if (dummy == 200)
         dummy = 0;
   }
}


When using the provided startup object the interrupt qualifier is not needed. Also you need to enable the interrupts yourself (asm cli;) as this is not done in the startup code apparently.

Now the interrupt works.


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

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 15 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: