Problem getting RLPext to work

I am trying to get the RLPext functionality to work on my Cobra. I am using the following RLP native code:



 #include "RLP.h"

/****************************************************************************************************
 * Requires 7 unsigned int arguments:																*
 * DOGInitialize.Invoke(csPinNbr, clkPinNbr, cmdPinNbr, rstPinNbr,datPinNbr, blPinNbr, byteArray);	*
 ***************************************************************************************************/
int Initialize(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
	// save the control pin numbers
	unsigned int LCDCS = *(unsigned char*)args[0];
	unsigned int LCDCLK = *(unsigned char*)args[1];
	unsigned int LCDCMD = *(unsigned char*)args[2];
	unsigned int LCDRST = *(unsigned char*)args[3];
	unsigned int LCDDAT = *(unsigned char*)args[4];
	unsigned int LCDBL = *(unsigned char*)args[5];

	unsigned char* byteArray = (unsigned char*)args[6];

	byteArray[0] = LCDCS;
	byteArray[1] = LCDCLK;
	byteArray[2] = LCDCMD;
	byteArray[3] = LCDRST;
	byteArray[4] = LCDDAT;
	byteArray[5] = LCDBL;

	RLPext->GPIO.WritePin(LCDBL, RLP_TRUE);	// backlight is on

	return 5;	// return some value
}

I created a wrapper class for the native code as follows:


using System;
using Microsoft.SPOT;
using GHIElectronics.NETMF.Native;
using Microsoft.SPOT.Hardware;

namespace DogLcdRlpWrapperClass
{
    class DogLcdRlpWrapper
    {
        RLP.Procedure DOGInitialize;

        /// <summary>
        /// Creates an instance of the DOG LCD wrapper class
        /// </summary>
        /// <param name="elfImage">
        /// The ELF image to load
        /// </param>
        public DogLcdRlpWrapper(byte[] elfImage)
        {
            // InitializeElf(elfImage);
            // load the ELF image
            RLP.LoadELF(elfImage);
            // init the BSS memory region to zeros
            RLP.InitializeBSSRegion(elfImage);
            // get the all the RLP procedures
            DOGInitialize = RLP.GetProcedure(elfImage, "Initialize");
        }
        /// <summary>
        /// Initializes the LCD
        /// </summary>
        /// <returns></returns>
        public int Initialize(byte csPin, byte clkPin, byte cmdPin, byte rstPin, byte datPin, byte blPin)
        {
            byte[] array = new byte[10] {1,2,3,4,5,6,7,8,9,0};

            int result = DOGInitialize.Invoke(csPin, clkPin, cmdPin, rstPin, datPin, blPin, array);
            return result;
        }
    }
}

And my test program is as follows:


using System;
using System.IO;
using System.Threading;

using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.IO;
using GHIElectronics.NETMF.Native;

using DogLcdRlpWrapperClass;
using SDCardFilesystemClass;

namespace DOG_LCD_Interface_Test
{
    public class Program
    {
        static byte[] elfImage = null;

        static OutputPort LCDCS;
        static OutputPort LCDCLK;
        static OutputPort LCDCMD;
        static OutputPort LCDRST;
        static OutputPort LCDDAT;
        static OutputPort LCDBL;
        
        public static void Main()
        {

            RLP.Unlock( /* <my unlock code is inserted here> */ );
            SDCardFilesystem sdFS = new SDCardFilesystem();
            if (sdFS != null)
            {
                FileStream fs = sdFS.OpenFile("\\SD\\RLPExtTest.elf", FileMode.Open, FileAccess.Read);
                if (fs != null)
                {
                    try
                    {
                        fs.Seek(0, SeekOrigin.End);
                        int flen = (int)fs.Position;
                        fs.Seek(0, SeekOrigin.Begin);
                        elfImage = new byte[flen];
                        int bytesRead = sdFS.ReadFile(fs, ref elfImage, elfImage.Length);
                        if (bytesRead != elfImage.Length)
                        {
                            elfImage = null;
                        }
                    }
                    catch (Exception ex)
                    {
                        elfImage = null;
                        Debug.Print(ex.Message);
                    }
                }
                sdFS.Unmount();
            }
            if (elfImage != null)
            {
                DogLcdRlpWrapper dogLcd = new DogLcdRlpWrapper(elfImage);
                if (dogLcd != null)
                {
                    // the following GPIO pin definitions are for the
                    // Cobra connected to the remote control I/O panel
                    byte csPin = 9;
                    byte clkPin = 12;
                    byte cmdPin = 11;
                    byte rstPin = 10;
                    byte datPin = 13;
                    byte blPin = 14;

                    // create the output ports to access the LCD hardware
                    LCDCS = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO9, true);
                    LCDCLK = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO12, false);
                    LCDCMD = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO11, false);
                    LCDRST = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO10, false);
                    LCDDAT = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO13, false);
                    LCDBL = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.IO14, false);
                    // initialize the LCD in native code
                    int stat = dogLcd.Initialize(csPin, clkPin, cmdPin, rstPin, datPin, blPin);
                }
            }
            // Blink board LED
            bool ledState = false;
            OutputPort led = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, ledState);
            while (true)
            {
                // Sleep for 500 milliseconds
                Thread.Sleep(500);
                // toggle LED state
                ledState = !ledState;
                led.Write(ledState);
            }
        }
    }
}

I created the ELF file for the native code using the yagarto tools and copied the ELF file to a SD card to load onto the Cobra. I then built the test appplication in VS2010 Express.

When I tested the application using the VS debugger to step through the code everything works until I get to the line of code that calls the native function “Initialize” in the RLP wrapper class. The code never returns from that call. In fact the results of that call was to render the Cobra unusable until I reloaded the firmware using the boot loader.

I then commented out the following line in the native code:


	RLPext->GPIO.WritePin(LCDBL, RLP_TRUE);	// backlight is on

and tried the application again. This time the call to Initialize returned as expected and the contents of array were as expected. This indicates that the native function Initialize executes properly. It also seems to indicate that the RLPext call is the problem.

I am using the latest GHI NETMF SDK (ver 4.1.5.0)

Any suggestions as to what I am doing wrong?

Any help will be appreciated.

Regards,
Synapsys

Do you use correct RLP_ADDRESS and RLP_SIZE values?

To erase your application, it is easier to use MFDeploy and then click Erase.

It is better to first try our starter example as is.
Then try our extension example.
Do these work fine?

Architect:

[quote]Do you use correct RLP_ADDRESS and RLP_SIZE values?
[/quote]

Yes, I believe so. I modified the RLP.h file to enable the EMX address and size.

Mike:

I tried but the Cobra won’t respond at all when it gets into whatever state it’s in after the problem occurs.

[quote]It is better to first try our starter example as is.
Then try our extension example.
Do these work fine?
[/quote]

I tried the RLP_Extensions_Example and it works just fine. Of course I had to add my RLP unlock code to the managed test app.

So then I moved my RLPExtTest native source code to the example directory and modified the makefile to compile it. I added the code to the managed test app to execute it and now it works :o

I still haven’t found out what my original problem is but it must have something to do with the makefile or RLP.h file I’m using in my build directory. I’ll keep looking for it and report back when (if) I find it.

Thanks for your help.

Regards,
Synapsys

On Cobra, you can hold up and down buttons on power up to keep the board in TinyBooter mode. From here, you can use erase feature on MFDeploy.

By the way, can we please use the new board for RLP from now on?
http://www.tinyclr.com/forum/17/2751/#/1/msg27044

I found the problem, I wrote a utility program I use to simplfy the RLP code build process. It had a bug in the creation of the RLP.h file that caused the address to drop a trailing 0. This caused the RLP code to load in the wrong place. Everything works fine now :-[

Gus: I will use the new place for RLP questions in the future.

Regards,
Synapsys