Question

I am attempting to use MonoTouch with the Redpark SDK and replicate in C# a Redpark serial cable example program written in Objective-C found here (that I was able to run perfectly in Xcode):

https://github.com/bjepson/iPhone-Arduino-Simple-Switch

I used an existing binding found here:

https://github.com/mono/monotouch-bindings/tree/master/Redpark

and created a .dll to use with my project. In my project, everything has been going smoothly (I was able to get the cableConnected and cableDisconnected delegate callbacks working well) up until trying to write. When I attempt to use the Write function, the program crashes with a SIGSEGV:

Stacktrace:

 at MonoTouch.RedPark.RscMgr.Write (int16,uint) <IL 0x00010, 0x00113>
  at tester2.tester2ViewController.toggleLED (MonoTouch.Foundation.NSObject) [0x00069] in /Users/salgarcia/Projects/tester2/tester2/tester2ViewController.cs:57
  at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
  at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38
  at tester2.Application.Main (string[]) [0x00000] in /Users/salgarcia/Projects/tester2/tester2/Main.cs:17
  at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>

Native stacktrace:

0   tester2                             0x001c2a25 mono_handle_native_sigsegv + 244
1   tester2                             0x001af065 mono_sigsegv_signal_handler + 172
2   libsystem_c.dylib                   0x329f17ed _sigtramp + 48
3   tester2                             0x00003a63 __inline_memcpy_chk + 30
4   tester2                             0x00003a63 __inline_memcpy_chk + 30
5   tester2                             0x00004011 -[RscMgr writeRscMessage:Length:MsgData:] + 220
6   tester2                             0x00004131 -[RscMgr write:Length:] + 100
7   tester2                             0x000438d8 wrapper_managed_to_native_ApiDefinition_Messaging_int_objc_msgSend_short_UInt32_intptr_intptr_int16_uint + 256
8   tester2                             0x001aa024 tester2_tester2ViewController_toggleLED_MonoTouch_Foundation_NSObject + 680
9   tester2                             0x000f76c0 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
10  tester2                             0x001b0843 mono_jit_runtime_invoke + 1054
11  tester2                             0x0022c40f mono_runtime_invoke + 90
12  tester2                             0x001ad14d native_to_managed_trampoline_tester2_tester2ViewController_toggleLED + 220
13  CoreFoundation                      0x3553f3fd -[NSObject performSelector:withObject:withObject:] + 52
14  UIKit                               0x33034e07 -[UIApplication sendAction:to:from:forEvent:] + 62
15  UIKit                               0x33034dc3 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 30
16  UIKit                               0x33034da1 -[UIControl sendAction:to:forEvent:] + 44
17  UIKit                               0x33034b11 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 492
18  Foundation                          0x350ff933 __NSFireDelayedPerform + 414
19  CoreFoundation                      0x355b9a33 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
20  CoreFoundation                      0x355b9699 __CFRunLoopDoTimer + 364
21  CoreFoundation                      0x355b826f __CFRunLoopRun + 1206
22  CoreFoundation                      0x3553b4a5 CFRunLoopRunSpecific + 300
23  CoreFoundation                      0x3553b36d CFRunLoopRunInMode + 104
24  GraphicsServices                    0x371d7439 GSEventRunModal + 136
25  UIKit                               0x33047cd5 UIApplicationMain + 1080
26  tester2                             0x0001fcc4 wrapper_managed_to_native_MonoTouch_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 240
27  tester2                             0x001a9744 tester2_Application_Main_string__ + 152
28  tester2                             0x000f76c0 wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 200
29  tester2                             0x001b0843 mono_jit_runtime_invoke + 1054
30  tester2                             0x0022c40f mono_runtime_invoke + 90
31  tester2                             0x0022f123 mono_runtime_exec_main + 306
32  tester2                             0x00232a4f mono_runtime_run_main + 482
33  tester2                             0x001b529f mono_jit_exec + 94
34  tester2                             0x00271c70 main + 2216
35  tester2                             0x00004860 start + 40

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

I'm looking for input for what might be the problem (i.e. the Serial port actually did not get opened, I could be using the wrong data type for "txbuffer", the binding was not implemented properly, I am not setting the delegate properly, etc.) Any feedback on this would be greatly appreciated!

For reference, here is the Objective-C implementation alongside my C#/MonoTouch implementation:

Objective-C ".h" file for Redpark library

#import <Foundation/Foundation.h>
#import <ExternalAccessory/ExternalAccessoryDefines.h>
#import <ExternalAccessory/EAAccessoryManager.h>
#import <ExternalAccessory/EAAccessory.h>
#import <ExternalAccessory/EASession.h>

#include "redparkSerial.h"



enum
{   
    kMsrCts = 0x01,
    kMsrRi =  0x02,
    kMsrDsr = 0x04,
    kMsrDcd = 0x08,

};

enum {
    kRSC_StreamBufferSize = 4096,
    kRSC_MaxMessageDataLength = 230,
    kRSC_SerialReadBufferSize = 4096,
    kRsc_TxFifoSize = 256,
    kRSC_NoPasscode = 0
};


typedef enum DataSizeType
{
    kDataSize7 = SERIAL_DATABITS_7,
    kDataSize8 = SERIAL_DATABITS_8
} DataSizeType;

typedef enum ParityType
{
    kParityNone = SERIAL_PARITY_NONE,
    kParityOdd = SERIAL_PARITY_ODD,
    kParityEven = SERIAL_PARITY_EVEN
} ParityType;

typedef enum StopBitsType
{
    kStopBits1 = STOPBITS_1,
    kStopBits2 = STOPBITS_2
} StopBitsType;


@protocol RscMgrDelegate;

@interface RscMgr : NSObject <NSStreamDelegate> {

    id <RscMgrDelegate> theDelegate;

    // EA api variables
    EASession *theSession;
    EAAccessory *theAccessory;
    NSArray *supportedProtocols;
    NSString *connectedProtocol;

    // rsc port control/info structures
    serialPortConfig portConfig;
    serialPortStatus portStatus;
    serialPortControl portControl;

    // EASession stream handling
    // for collecting RSC Messages
    unsigned char *rxStreamBuffer;
    int rxCount;
    int rxCountTotal;
    int txCountTotal;
    int rxRemain;
    int readLen;

    unsigned char *txStreamBuffer;
    int txIn;
    int txOut;
    int txStreamEmpty;

    // internal dtr and rts state bits
    int dtrState;
    int rtsState;   

    // serial data buffer
    // for collecting serial bytes received from the serial port
    UInt8 *serialReadBuffer;
    int serialReadIn;
    int serialReadOut;
    int serialReadBytesAvailable;

    BOOL encodingEnabled;   
    UInt32 thePasscode;

}

- (void) setDelegate:(id <RscMgrDelegate>) delegate;


// Initializes the RscMgr and reigsters for accessory connect/disconnect notifications. 
- (id) init;

// establish communication with the Redpark Serial Cable.  This call will also
// configure the serial port based on defaults or prior calls to set the port config
// (see setBaud, setDataSize, ...)
- (void) open;

// simple serial port config interface
// can be called anytime (even after open: call)
- (void) setBaud:(int)baud;
- (void) setDataSize:(DataSizeType)dataSize;
- (void) setParity:(ParityType)parity;
- (void) setStopBits:(StopBitsType)stopBits;

// read write serial bytes
- (int) write:(UInt8 *)data Length:(UInt32)length;
- (int) read:(UInt8 *)data Length:(UInt32)length;
- (int) getReadBytesAvailable;

/* 
 returns a bit field (see redparkSerial.h)
 0-3 current modem status bits for CTS, RI, DSR, DCD, 4-7 previous modem status bits

 MODEM_STAT_CTS  0x01
 MODEM_STAT_RI   0x02
 MODEM_STAT_DSR  0x04
 MODEM_STAT_DCD  0x08
 */
- (int) getModemStatus;

// returns true if DTR is asserted
- (BOOL) getDtr;

// returns true if RTS is asserted
- (BOOL) getRts;

// set DTR state 
- (void) setDtr:(BOOL)enable;

// set RTS state
- (void) setRts:(BOOL)enable;

// advanced (full) serial port config interface (see redparkSerial.h)
- (void) setPortConfig:(serialPortConfig *)config RequestStatus:(BOOL)reqStatus;
- (void) setPortControl:(serialPortControl *)control RequestStatus:(BOOL)reqStatus;
- (void) getPortConfig:(serialPortConfig *) portConfig;
- (void) getPortStatus:(serialPortStatus *) portStatus;

// advanced advanced
// write a raw message
- (int) writeRscMessage:(int)cmd Length:(int)len MsgData:(UInt8 *)msgData;

// GPS cable only - requires loopback connector
- (void) testGpsCable;

@end

@protocol RscMgrDelegate  <NSObject>

// Redpark Serial Cable has been connected and/or application moved to foreground.
// protocol is the string which matched from the protocol list passed to initWithProtocol:
- (void) cableConnected:(NSString *)protocol;

// Redpark Serial Cable was disconnected and/or application moved to background
- (void) cableDisconnected;

// serial port status has changed
// user can call getModemStatus or getPortStatus to get current state
- (void) portStatusChanged;

// bytes are available to be read (user calls read:)
- (void) readBytesAvailable:(UInt32)length;

@optional
// called when a response is received to a getPortConfig call
- (void) didReceivePortConfig;

// GPS Cable only - called with result when loop test completes.  
- (void) didGpsLoopTest:(BOOL)pass;

@end

Objective-C ".h" file

#import <UIKit/UIKit.h>
#import "RscMgr.h"

#define BUFFER_LEN 1024

@interface HelloArduinoViewController : UIViewController <RscMgrDelegate> {

RscMgr *rscMgr;
UInt8 rxBuffer[BUFFER_LEN];
UInt8 txBuffer[BUFFER_LEN];

UISwitch *toggleSwitch;
}

@property (nonatomic, retain) IBOutlet UISwitch *toggleSwitch;
- (IBAction)toggleLED:(id)sender;

@end

Objective-C ".m" file

#import "HelloArduinoViewController.h"

@implementation HelloArduinoViewController
@synthesize toggleSwitch;

- (void)dealloc
{
    [toggleSwitch release];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    [super viewDidLoad];
    rscMgr = [[RscMgr alloc] init]; 
    [rscMgr setDelegate:self];

}


- (void)viewDidUnload
{
    [self setToggleSwitch:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (IBAction)toggleLED:(id)sender {
    if (toggleSwitch.on) { // check the state of the button
        txBuffer[0] = (int) '1';
    } else {
        txBuffer[0] = (int) '0';
    }

    // Send 0 or 1 to the Arduino
    [rscMgr write:txBuffer Length:1];        
}

#pragma mark - RscMgrDelegate methods

- (void) cableConnected:(NSString *)protocol {
    [rscMgr setBaud:9600];
    [rscMgr open]; 
}

- (void) cableDisconnected {

}

- (void) portStatusChanged {

}

- (void) readBytesAvailable:(UInt32)numBytes {
}

- (BOOL) rscMessageReceived:(UInt8 *)msg TotalLength:(int)len {
    return FALSE;    
}

- (void) didReceivePortConfig {
}

@end

My C#/MonoTouch implementation

using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.RedPark;

namespace tester2
{
    public partial class tester2ViewController : UIViewController
    {
        static RscMgr rscMgr;
        MyRedparkDelegate delegate1;

        short[] rxbuffer = new short[1024];
        short[] txbuffer = new short[1024];

        public tester2ViewController () : base ("tester2ViewController", null)
        {
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
        }

        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            rscMgr = new RscMgr();
            delegate1 = new MyRedparkDelegate ();
            rscMgr.SetDelegate(delegate1);
        }

        public override void ViewDidUnload ()
        {
            base.ViewDidUnload ();
            ReleaseDesignerOutlets ();
        }

        public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
        {
            return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
        }

        partial void toggleLED (NSObject sender)
        {
            if(toggleSwitch.On) {
                txbuffer[0] = (int) '1';
            } else {
                txbuffer[0] = (int) '0';
            }
            rscMgr.Write (txbuffer[0], 1);
        }

        public class MyRedparkDelegate : RscMgrDelegate
        {
            public MyRedparkDelegate ()
            {
            }
            public override void CableConnected (string protocol)
            {
                rscMgr.SetBaud (9600);
                rscMgr.Open ();
            }
            public override void CableDisconnected ()
            {
            }
            public override void PortStatusChanged ()
            {
            }
            public override void ReadBytesAvailable (uint length)
            {
            }
        }
    }
}
Was it helpful?

Solution

The problem was solved in my MonoTouch implementation code, where I found that I needed to pass the data being written by reference, so I changed the Write in the code above to

     rscMgr.Write(ref txbuffer[0],1);

and it worked as expected. It helped thoroughly reading the Redpark Serial cable SDK User guide that came with the SDK download.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top