Jump to content

Status of SDCC evaluation


TK.

Recommended Posts

Triggered from the midiboxchat today I evalued the SDCC, an open source C compiler which is available under http://sdcc.sourceforge.net.

I programmed a so called "wrapper" which maps some of the MIOS functions to the C world, so that they are accessible as common C functions:

extern void MIOS_LCD_Clear(void);
extern void MIOS_LCD_CursorSet(char pos);
extern void MIOS_LCD_PrintChar(char c);
extern void MIOS_LCD_PrintString(char *str);
extern void MIOS_LCD_PrintPreconfString(char *str);
Two MIOS hooks directly branched to the C program:
USER_Init
        extern  _CMIOS_Init
        goto    _CMIOS_Init     

USER_DISPLAY_Init
        extern  _CMIOS_DISPLAY_Init
        goto    _CMIOS_DISPLAY_Init     
so that following C code was possible:
void CMIOS_Init(void)
{
}

void CMIOS_DISPLAY_Init(void)
{
   MIOS_LCD_Clear();
   MIOS_LCD_CursorSet(0x00);
   MIOS_LCD_PrintChar('1');
   MIOS_LCD_PrintChar('2');
   MIOS_LCD_PrintChar('3');
}
This was working and the resulting assembler code looked exactly like I would program it in assembler. Then I tried to output a string:
static char[] = {12, 0x00, "Hello World!"}

void CMIOS_DISPLAY_Init(void)
{
   MIOS_LCD_Clear();
   MIOS_LCD_PrintString(hello_world);
}
But the static string above produced a table with following entries
_hello_world    db      0x0c, 0x00, 0xa8
It seems that the compiler feels confused about a mix of constant values and characters Next try:
void CMIOS_DISPLAY_Init(void)
{
   MIOS_LCD_Clear();
   MIOS_LCD_CursorSet(0x00);
   MIOS_LCD_PrintPreconfString("Hello World!");
}
but no luck: the compiler crashed with a signal error - bad, it seems that the PIC18F module hasn't been programmed properly enough. Last try:
void CMIOS_DISPLAY_Init(void)
{
   int i;

   MIOS_LCD_Clear();
   MIOS_LCD_CursorSet(0x00);

   for(i=0; i<3; ++i)
   {
      MIOS_LCD_PrintChar('A' + xx);
   }
}
This produced so much assembler code that it was definitely clear to me that SDCC is the wrong way to program a powerfull application:
;#LINE   7; main.c       void CMIOS_DISPLAY_Init(void)
        MOVFF   FSR2L, POSTDEC1
        MOVFF   FSR1L, FSR2L
        MOVFF   r0x10, POSTDEC1
        MOVFF   r0x11, POSTDEC1
;#LINE   11; main.c      MIOS_LCD_Clear();
        CALL    _MIOS_LCD_Clear
;#LINE   12; main.c      MIOS_LCD_CursorSet(0x00);
        MOVLW   0x00
        CALL    _MIOS_LCD_CursorSet
;#LINE   14; main.c      for(i=0; i<3; ++i)
        CLRF    r0x10
_00109_DS_:
        MOVLW   0x03
        SUBWF   r0x10, W
        BTFSC   STATUS,0
        GOTO    _00113_DS_
;#LINE   16; main.c      MIOS_LCD_PrintChar('A' + i);
        MOVLW   0x41
        ADDWF   r0x10, W
        MOVWF   r0x11
        MOVF    r0x11, W
        CALL    _MIOS_LCD_PrintChar
;#LINE   14; main.c      for(i=0; i<3; ++i)
        INCF    r0x10, F
        GOTO    _00109_DS_
_00113_DS_:
        MOVFF   PREINC1, r0x11
        MOVFF   PREINC1, r0x10
;;genEndFunction: _G.nRegsSaved upon exit from function: 0

        MOVFF   PREINC1, FSR2L
        RETURN  
Just to compare it with handwritten assembler code:
_CMIOS_DISPLAY_Init:
      ;; stack handling excluded here
      call      MIOS_LCD_Clear
      movlw      0x00
      call      MIOS_LCD_CursorSet
      clrf      r0x10
_CMIOS_DISPLAY_Init_Loop:
      movlw      0x41
      addwf      rx010, W
      call      MIOS_LCD_PrintChar
      incf      rx010, F
      movlw      0x03-1
      cpfsgt      rx010
      bra      _CMIOS_DISPLAY_Init_Loop
      ;; stack handling excluded here
      return

Conclusion:


     
  • the SDCC crashes sometimes and will therefore be hard to use for people who just want to write some lines of code without knowing about those quirks
     
  • the code optimization is far from perfection, it seems that the compiler doesn't know about all those nice new PIC18F instructions which help to make the code shorter
     
  • the compiler produces too much code, therefore the applications cannot include so much features anymore
     
  • the compiler allocates all three pointers (FSR0-FSR2), therefore some code changes will be required in MIOS which will slow down the system (especially on interrupts)
     
  • who knows which problems I haven't seen yet...

I'm not sure if currently the C approach is worth the effort...

Best Regards, Thorsten.

Link to comment
Share on other sites

Hi,

SDCC has a special "pic16" module, and pic16 means "16 bit architecture" here - thats the PIC18F family

However, rumors told me that there will be some improvements in the future which will allow to interact with MIOS without big performance loss.

Best Regards, Thorsten.

Link to comment
Share on other sites

Good news: I'm in contact with Vangelis, the developer of the PIC16 SDCC module. Maybe we will find a good solution to improve the interaction with MIOS, and to optimize the assembler output :)

Best Regards, Thorsten.

Link to comment
Share on other sites

Here a first insight into a C programming example:

#include "cmios.h"
//#include <pic18f452.h>


/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after startup to initialize the 
// application
/////////////////////////////////////////////////////////////////////////////
void Init(void)
{
   // define number of shift registers
   MIOS_SRIO_NumberSet(16);

   // update frequency of SRIO chain
   MIOS_SRIO_UpdateFrqSet(1); // ms
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void)
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when the display content should be 
// initialized. Thats the case during startup and after a temporary message
// has been printed on the screen
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Init(void)
{
   // clear screen
   MIOS_LCD_Clear();

   // print message
   MIOS_LCD_CursorSet(0x00);
   MIOS_LCD_PrintCString("Press Button");
}

/////////////////////////////////////////////////////////////////////////////
//  This function is called in the mainloop when no temporary message is shown
//  on screen. Print the realtime messages here
/////////////////////////////////////////////////////////////////////////////
void DISPLAY_Tick(void)
{
}

/////////////////////////////////////////////////////////////////////////////
//  This function is called by MIOS when a complete MIDI event has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2)
{
   // print received MIDI event
   MIOS_LCD_Clear();

   MIOS_LCD_PrintCString("Received:");

   MIOS_LCD_CursorSet(0x40);
   MIOS_LCD_PrintHex2(evnt0);
   MIOS_LCD_PrintHex2(evnt1);
   MIOS_LCD_PrintHex2(evnt2);
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has been received
// which has been specified in the MIOS_MPROC_EVENT_TABLE
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyFoundEvent(unsigned entry, unsigned char evnt0, unsigned char evnt1, unsigned char envt2)
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI event has not been completly
// received within 2 seconds
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyTimeout(void)
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a MIDI byte has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedByte(unsigned char byte)
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an button has been toggled
// pin_value is 1 when button released, and 0 when button pressed
/////////////////////////////////////////////////////////////////////////////
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value)
{
   MIOS_LCD_Clear();

   MIOS_LCD_PrintCString("DIN #");
   MIOS_LCD_PrintBCD3(pin);

   MIOS_LCD_PrintCString(pin_value ? " off" : " on");

   MIOS_LCD_CursorSet(0x40);
   switch( pin )
   {
      case 0:
         MIOS_LCD_PrintCString("Sending a Note");
         MIOS_MIDI_TxBufferPut(0x90);
         MIOS_MIDI_TxBufferPut(pin);
         MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f);
         break;

      case 1:
         MIOS_LCD_PrintCString("Sending a CC");
         MIOS_MIDI_TxBufferPut(0xb0);
         MIOS_MIDI_TxBufferPut(pin);
         MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f);
         break;

      case 2:
         MIOS_LCD_PrintCString("Sending SysEx");
         MIOS_MIDI_TxBufferPut(0xf0);
         MIOS_MIDI_TxBufferPut(0x11);
         MIOS_MIDI_TxBufferPut(0x22);
         MIOS_MIDI_TxBufferPut(0x33);
         MIOS_MIDI_TxBufferPut(0x44);
         MIOS_MIDI_TxBufferPut(pin);
         MIOS_MIDI_TxBufferPut(pin_value ? 0x00 : 0x7f);
         MIOS_MIDI_TxBufferPut(0xf7);
         break;

      default:
         MIOS_LCD_PrintCString("No action");
   }
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an encoder has been moved
// incrementer is positive when encoder has been turned clockwise, else
// it is negative
/////////////////////////////////////////////////////////////////////////////
void ENC_NotifyChange(unsigned char encoder, unsigned char incrementer)
{
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when a pot has been moved
/////////////////////////////////////////////////////////////////////////////
void AIN_NotifyChange(unsigned char pin, unsigned int pin_value)
{
}

all MIOS functions are now accessible from C

I've written a small script which builds workarounds into the generated assembler code. Some of them will be part of the next SDCC release.

If anybody wants to beta-test the MIOS wrapper, just write me an email.

Best Regards, Thorsten.

Link to comment
Share on other sites

I've got one question about this C stuff, is it possible to make big apps like the LC one?

I wish to make a midibox like the digidesign ProControl to use with ardour (I don't know yet how ardour will works with control surface, as it's not fully working by now), and if can do this in C.... could be great as many switch can be used for more than one function (I think about making a finish state machine).

Link to comment
Share on other sites

  • 4 weeks later...

here's the makefile for the mios C wrapper (using sdcc and gputils) :

project.hex:      main.c
      gpasm -c mios_wrapper/mios_wrapper.asm -I mios_wrapper -o mios_wrapper.o
      sdcc -S -V -mpic16 -p18F452 --pomit-config-words --pomit-ivt -pleave-reset-vector main.c 
      perl tools/fixasm.pl main.asm
      gpasm -c main.asm
      gplink main.o mios_wrapper.o -s project.lkr -o project.hex
      perl tools/hex2syx.pl project.hex

gputils can be found here (open source pic asm compiler) :

http://gputils.sourceforge.net/

Link to comment
Share on other sites

  • 3 weeks later...
Guest nomadicWhale

2 things?

1. How can I use global varaibles in a cmios application?

Can I just define them as I would define them in a regular c program? will the linker know what addresses to assign to them so that they will not override mios reserved memory locations?

Maybe someone have an example...

2. Just to be safe, the project.syx produced by the make.bat file is the file I need to upload to my MB?

Thanks

nW

Link to comment
Share on other sites

Guest nomadicWhale

some updates...

1. global varaibles can be defined as you ususal, out of the scope of any method.

2. I'm currently having problems defining automatic varaibles (varaibles inside methods)... any help/example would be great.

3. and obviously enough the project.sysx is the one to upload to mios....

nW

Link to comment
Share on other sites

Thanks for the input, Pilo! :-)

nW: yes, you can use global variables. Just look into the generated assembler file to see what SDCC is doing with these variables.

Yes, you need the preliminary release of MIOS V1.8, otherwise your program will crash due to overwritten FSR2[LH]

More infos can be found at the MIOS C introduction page:

http://www.ucapps.de/mios_c.html

Best Regards, Thorsten.

Link to comment
Share on other sites

  • 2 weeks later...

I think there's a problem with MIOS_MF_FaderMove function,

.MIOS_MF_FaderMove code
_MIOS_MF_FaderMove
      global      _MIOS_MF_FaderMove

      movwf      MIOS_PARAMETER1
      movff      FSR0L, FSR2L
       movff      PREINC2, MIOS_PARAMETER2
       movff      PREINC2, MIOS_PARAMETER1
      goto      MIOS_MF_FaderMove
I put this instead of this :
.MIOS_MF_FaderMove code
_MIOS_MF_FaderMove
      global      _MIOS_MF_FaderMove

      movwf      MIOS_PARAMETER1
      movff      FSR0L, FSR2L
       movff      PREINC2, MIOS_PARAMETER2
       movf      PREINC2, W
      goto      MIOS_MF_FaderMove

And now it seems to work well.

Link to comment
Share on other sites

Hi Pilo,

thanks for the input. I cannot explain while your variant should work better (since MIOS_PARAMETER1 is overwritten), but I will try this out with my MBLC hardware and bring the fixed code into the first official release.

Best Regards, Thorsten.

Link to comment
Share on other sites

I cannot explain while your variant should work better

I can't too... :-[

Actually the problem was that pin and pin_value was inverted in C wrapper... so I try to put that in the right way. And I couldn't wait to test some C code ;) That's why I made this changed, without really knowing why it works (I try to put the right value in mios_parameter1 instead of W).

By the way making apps with C and MIOS is real fun... ;D

Link to comment
Share on other sites

By the way making apps with C and MIOS is real fun...

I hope so! :-)

I must admit that I haven't worked on the C wrapper anymore after the night I wrote it ;-)

So your error reports are really welcome :)

Currently I'm working on vmidibox64 and vmidibox64e (C++ fun under windows), hope that I will find some time thereafter to finalize the wrapper

BestRegards, Thorsten.

Link to comment
Share on other sites

hehe ;)

I'm currently soldering the din and dout for the matrix stuff, then test it with C wrapper (I will include the matrix stuff in mios_wrapper.asm). Then I can start to ake more stuff :)

As soon as I have a working setup(switch and encoder), I will make basics C tutorials (or maybe somebody else start this?), to show how it's easy now to make MIOS apps ;) I need to clean up and even rewrite the make file, the rules are wrong (I use rules for project.hex but the makefile convert it to syx, and I don't put rules for mios_wrapper.o).

Link to comment
Share on other sites

  • 2 months later...

I'm getting some stange LCD behavior with the wrapper: calls to MIOS_LCD_PrintCString result in black spaces between each character in the string.  For example, "dog" prints as "d_o_g" where "_" represents a solid black block.  

If I use MIOS_LCD_PrintChar, everything works fine.  

Any ideas??!

-Graham

Link to comment
Share on other sites

  • 1 month later...

Thanks TK !

The timer is up and running as a swiss clock now :)

Now I have some other problems, but I don't think this is the right thread to ask them in. So how about a new topic under "MIOS programming", "C programming" or something like that ? Just to separate "MIOS asm" and "MIOS C".

/Wise

Link to comment
Share on other sites

Hi Wise,

I will open a new section once the C wrapper is officially released. In the meantime you can ask in a seperate thread.

Btw. - the current status: in the last weeks some changes were included into SDCC which makes it incompatible to the wrapper. In the meantime I was able to adapt it to the changes, but there are still some open issues which have to be solved. Issues means here: bugs in the compiler.

From time to time I'm submitting bug reports to the SDCC bug database, they were always fixed immediately. So, there is hope that we get the things sorted in 2-3 weeks.

Best Regards, Thorsten.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...