Skip to content

Commit

Permalink
Update and rework System.Device.Gpio (#1742)
Browse files Browse the repository at this point in the history
  • Loading branch information
josesimoes authored Oct 22, 2020
1 parent cb52d57 commit fcec675
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 98 deletions.
8 changes: 4 additions & 4 deletions src/System.Device.Gpio/sys_dev_gpio_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ static const CLR_RT_MethodHandler method_lookup[] =
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Toggle___VOID,
NULL,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::DisposeNative___VOID,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeIsDriveModeSupported___BOOLEAN__SystemDeviceGpioPinMode,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetDriveMode___VOID__SystemDeviceGpioPinMode,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeIsPinModeSupported___BOOLEAN__SystemDeviceGpioPinMode,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetPinMode___VOID__SystemDeviceGpioPinMode,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeInit___BOOLEAN__I4,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetDebounceTimeout___VOID,
Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::WriteNative___VOID__SystemDeviceGpioPinValue,
Expand Down Expand Up @@ -100,9 +100,9 @@ static const CLR_RT_MethodHandler method_lookup[] =
const CLR_RT_NativeAssemblyData g_CLR_AssemblyNative_System_Device_Gpio =
{
"System.Device.Gpio",
0xB88842A6,
0xB6D0ACC1,
method_lookup,
{ 100, 1, 0, 1 }
{ 100, 1, 0, 3 }
};

// clang-format on
57 changes: 31 additions & 26 deletions src/System.Device.Gpio/sys_dev_gpio_native.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <nanoCLR_Runtime.h>
#include <nanoPackStruct.h>
#include <corlib_native.h>
#include <CPU_GPIO_decl.h>

typedef enum __nfpack PinEventTypes
{
Expand All @@ -31,6 +32,7 @@ typedef enum __nfpack PinEventTypes
// PinMode_OutputOpenSource = 6,
// PinMode_OutputOpenSourcePullDown = 7,
// } PinMode;
typedef GpioPinDriveMode PinMode;

struct Library_sys_dev_gpio_native_System_Device_Gpio_PinValue
{
Expand All @@ -39,34 +41,13 @@ struct Library_sys_dev_gpio_native_System_Device_Gpio_PinValue
//--//
};

struct Library_sys_dev_gpio_native_System_Device_Gpio_GpioController
{
static const int FIELD_STATIC__s_GpioPins = 0;
static const int FIELD_STATIC___syncLock = 1;

static const int FIELD___disposedValue = 1;
static const int FIELD___NumberingScheme_k__BackingField = 2;

NANOCLR_NATIVE_DECLARE(get_PinCount___I4);
NANOCLR_NATIVE_DECLARE(DisposeNative___VOID);
NANOCLR_NATIVE_DECLARE(IsPinModeSupported___BOOLEAN__I4__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(IsPinOpen___BOOLEAN__I4);
NANOCLR_NATIVE_DECLARE(SetPinMode___VOID__I4__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeRead___U1__I4);
NANOCLR_NATIVE_DECLARE(NativeWrite___VOID__I4__U1);

//--//

static void GetGpioPin(CLR_INT32 index, CLR_RT_StackFrame &stack, CLR_RT_HeapBlock *&gpioPin);
};

struct Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin
{
static const int FIELD_STATIC__s_gpioPinEventManager = 2;
static const int FIELD_STATIC__s_gpioPinEventManager = 0;

static const int FIELD___syncLock = 1;
static const int FIELD___pinNumber = 2;
static const int FIELD___driveMode = 3;
static const int FIELD___pinMode = 3;
static const int FIELD___debounceTimeout = 4;
static const int FIELD___callbacks = 5;
static const int FIELD___lastOutputValue = 6;
Expand All @@ -76,16 +57,40 @@ struct Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin
NANOCLR_NATIVE_DECLARE(Read___SystemDeviceGpioPinValue);
NANOCLR_NATIVE_DECLARE(Toggle___VOID);
NANOCLR_NATIVE_DECLARE(DisposeNative___VOID);
NANOCLR_NATIVE_DECLARE(NativeIsDriveModeSupported___BOOLEAN__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeSetDriveMode___VOID__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeIsPinModeSupported___BOOLEAN__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeSetPinMode___VOID__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeInit___BOOLEAN__I4);
NANOCLR_NATIVE_DECLARE(NativeSetDebounceTimeout___VOID);
NANOCLR_NATIVE_DECLARE(WriteNative___VOID__SystemDeviceGpioPinValue);
NANOCLR_NATIVE_DECLARE(NativeSetAlternateFunction___VOID__I4);
NANOCLR_NATIVE_DECLARE(NativeInit___BOOLEAN__I4);

//--//

static HRESULT ExtractDebounceTimeSpanValue(CLR_RT_HeapBlock &timeSpanValue, CLR_UINT64 &value);
static HRESULT SetPinMode(CLR_RT_HeapBlock *gpioPin, GpioPinDriveMode pinMode);
static HRESULT Write(CLR_RT_HeapBlock *gpioPin, bool pinValue);
static HRESULT Read(CLR_RT_HeapBlock *gpioPin, bool &pinValue);
};

struct Library_sys_dev_gpio_native_System_Device_Gpio_GpioController
{
static const int FIELD_STATIC__s_GpioPins = 1;
static const int FIELD_STATIC___syncLock = 2;

static const int FIELD___disposedValue = 1;
static const int FIELD___NumberingScheme_k__BackingField = 2;

NANOCLR_NATIVE_DECLARE(get_PinCount___I4);
NANOCLR_NATIVE_DECLARE(DisposeNative___VOID);
NANOCLR_NATIVE_DECLARE(IsPinModeSupported___BOOLEAN__I4__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(IsPinOpen___BOOLEAN__I4);
NANOCLR_NATIVE_DECLARE(SetPinMode___VOID__I4__SystemDeviceGpioPinMode);
NANOCLR_NATIVE_DECLARE(NativeRead___U1__I4);
NANOCLR_NATIVE_DECLARE(NativeWrite___VOID__I4__U1);

//--//

static void GetGpioPin(CLR_INT32 index, CLR_RT_StackFrame &stack, CLR_RT_HeapBlock *&gpioPin);
};

struct Library_sys_dev_gpio_native_System_Device_Gpio_GpioPinBundle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioController::SetPinMod

GPIO_PIN pinNumber;
GpioPinDriveMode driveMode;
bool validPin;
CLR_RT_HeapBlock *gpioPin = NULL;

CLR_RT_HeapBlock *pThis = stack.This();
FAULT_ON_NULL(pThis);
Expand All @@ -79,20 +79,16 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioController::SetPinMod
pinNumber = (GPIO_PIN)stack.Arg1().NumericByRef().s4;
driveMode = (GpioPinDriveMode)stack.Arg2().NumericByRef().s4;

if (driveMode >= (int)GpioPinDriveMode_Output)
{
validPin = CPU_GPIO_EnableOutputPin(pinNumber, GpioPinValue_Low, (GpioPinDriveMode)driveMode);
}
else
{
validPin = CPU_GPIO_EnableInputPin(pinNumber, -1, NULL, NULL, GPIO_INT_EDGE_BOTH, (GpioPinDriveMode)driveMode);
}
// try to get GpioPin object
GetGpioPin(pinNumber, stack, gpioPin);

if (!validPin)
if (gpioPin == NULL)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
}

NANOCLR_CHECK_HRESULT(GpioPin::SetPinMode(gpioPin, driveMode));

NANOCLR_NOCLEANUP();
}

Expand All @@ -101,6 +97,7 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioController::NativeRea
NANOCLR_HEADER();

GPIO_PIN pinNumber;
bool pinValue;
CLR_RT_HeapBlock *gpioPin = NULL;

CLR_RT_HeapBlock *pThis = stack.This();
Expand All @@ -121,8 +118,10 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioController::NativeRea
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
}

// read pin and set result
stack.SetResult_U1(CPU_GPIO_GetPinState(pinNumber));
NANOCLR_CHECK_HRESULT(GpioPin::Read(gpioPin, pinValue));

// set result
stack.SetResult_I4(pinValue);

NANOCLR_NOCLEANUP();
}
Expand Down Expand Up @@ -155,11 +154,7 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioController::NativeWri
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_OPERATION);
}

// write to pin
CPU_GPIO_SetPinState(pinNumber, state);

// store the output value in the field
gpioPin[GpioPin::FIELD___lastOutputValue].NumericByRef().s4 = state;
NANOCLR_CHECK_HRESULT(GpioPin::Write(gpioPin, state));

NANOCLR_NOCLEANUP();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Read___SystemDev
{
NANOCLR_HEADER();
{
bool pinValue;

CLR_RT_HeapBlock *pThis = stack.This();
FAULT_ON_NULL(pThis);

Expand All @@ -27,9 +29,9 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Read___SystemDev
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
}

GPIO_PIN pinNumber = (GPIO_PIN)pThis[FIELD___pinNumber].NumericByRefConst().s4;
NANOCLR_CHECK_HRESULT(Read(pThis, pinValue));

stack.SetResult_I4(CPU_GPIO_GetPinState(pinNumber));
stack.SetResult_I4(pinValue);
}
NANOCLR_NOCLEANUP();
}
Expand All @@ -48,7 +50,7 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Toggle___VOID(CL
}

GPIO_PIN pinNumber = (GPIO_PIN)pThis[FIELD___pinNumber].NumericByRefConst().s4;
GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[FIELD___driveMode].NumericByRefConst().s4;
GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[FIELD___pinMode].NumericByRefConst().s4;

// sanity check for drive mode set to output so we don't mess up writing to an input pin
if (driveMode >= GpioPinDriveMode_Output)
Expand Down Expand Up @@ -86,7 +88,7 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::DisposeNative___
}

HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::
NativeIsDriveModeSupported___BOOLEAN__SystemDeviceGpioPinMode(CLR_RT_StackFrame &stack)
NativeIsPinModeSupported___BOOLEAN__SystemDeviceGpioPinMode(CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();
{
Expand All @@ -103,15 +105,11 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::
NANOCLR_NOCLEANUP();
}

HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetDriveMode___VOID__SystemDeviceGpioPinMode(
HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetPinMode___VOID__SystemDeviceGpioPinMode(
CLR_RT_StackFrame &stack)
{
NANOCLR_HEADER();
{
bool validPin;
CLR_UINT64 debounceTimeoutMilsec;
bool callbacksRegistered = false;

CLR_RT_HeapBlock *pThis = stack.This();
FAULT_ON_NULL(pThis);

Expand All @@ -120,34 +118,9 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::NativeSetDriveMo
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
}

GPIO_PIN pinNumber = (GPIO_PIN)pThis[FIELD___pinNumber].NumericByRefConst().s4;
GpioPinDriveMode driveMode = (GpioPinDriveMode)stack.Arg1().NumericByRef().s4;

if (driveMode >= (int)GpioPinDriveMode_Output)
{
validPin = CPU_GPIO_EnableOutputPin(pinNumber, GpioPinValue_Low, driveMode);
}
else
{
NANOCLR_CHECK_HRESULT(ExtractDebounceTimeSpanValue(pThis[FIELD___debounceTimeout], debounceTimeoutMilsec));

// flag to determine if there are any callbacks registered in managed code
// this is use to determine if there is any need to setup and process INT handler
callbacksRegistered = (pThis[FIELD___callbacks].Dereference() != NULL);

validPin = CPU_GPIO_EnableInputPin(
pinNumber,
debounceTimeoutMilsec,
callbacksRegistered ? Gpio_Interupt_ISR : NULL,
NULL,
GPIO_INT_EDGE_BOTH,
driveMode);
}

if (!validPin)
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}
NANOCLR_CHECK_HRESULT(SetPinMode(pThis, driveMode));

// protect this from GC so that the callback is where it's supposed to
CLR_RT_ProtectFromGC gc(*pThis);
Expand Down Expand Up @@ -191,23 +164,9 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::WriteNative___VO
NANOCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED);
}

GPIO_PIN pinNumber = (GPIO_PIN)pThis[FIELD___pinNumber].NumericByRefConst().s4;
GpioPinDriveMode driveMode = (GpioPinDriveMode)pThis[FIELD___driveMode].NumericByRefConst().s4;

GpioPinValue state = (GpioPinValue)stack.Arg1().NumericByRef().s4;

// sanity check for drive mode set to output so we don't mess up writing to an input pin
if ((driveMode >= GpioPinDriveMode_Output))
{
CPU_GPIO_SetPinState(pinNumber, state);

// store the output value in the field
pThis[FIELD___lastOutputValue].NumericByRef().s4 = state;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}
NANOCLR_CHECK_HRESULT(Write(pThis, state));
}
NANOCLR_NOCLEANUP();
}
Expand Down Expand Up @@ -264,3 +223,81 @@ HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::ExtractDebounceT
}
NANOCLR_NOCLEANUP();
}

HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::SetPinMode(
CLR_RT_HeapBlock *gpioPin,
GpioPinDriveMode pinMode)
{
NANOCLR_HEADER();

bool validPin;
CLR_UINT64 debounceTimeoutMilsec;
bool callbacksRegistered = false;

GPIO_PIN pinNumber = (GPIO_PIN)gpioPin[FIELD___pinNumber].NumericByRefConst().s4;

if (pinMode >= (int)GpioPinDriveMode_Output)
{
validPin = CPU_GPIO_EnableOutputPin(pinNumber, GpioPinValue_Low, pinMode);
}
else
{
NANOCLR_CHECK_HRESULT(ExtractDebounceTimeSpanValue(gpioPin[FIELD___debounceTimeout], debounceTimeoutMilsec));

// flag to determine if there are any callbacks registered in managed code
// this is use to determine if there is any need to setup and process INT handler
callbacksRegistered = (gpioPin[FIELD___callbacks].Dereference() != NULL);

validPin = CPU_GPIO_EnableInputPin(
pinNumber,
debounceTimeoutMilsec,
callbacksRegistered ? Gpio_Interupt_ISR : NULL,
NULL,
GPIO_INT_EDGE_BOTH,
pinMode);
}

if (validPin)
{
// all good, store pin mode in managed field
gpioPin[FIELD___pinMode].NumericByRef().s4 = pinMode;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

NANOCLR_NOCLEANUP();
}

HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Write(CLR_RT_HeapBlock *gpioPin, bool pinValue)
{
NANOCLR_HEADER();

GPIO_PIN pinNumber = (GPIO_PIN)gpioPin[FIELD___pinNumber].NumericByRefConst().s4;
GpioPinDriveMode driveMode = (GpioPinDriveMode)gpioPin[FIELD___pinMode].NumericByRefConst().s4;

// sanity check for drive mode set to output so we don't mess up writing to an input pin
if ((driveMode >= GpioPinDriveMode_Output))
{
CPU_GPIO_SetPinState(pinNumber, (GpioPinValue)pinValue);

// store the output value in the field
gpioPin[FIELD___lastOutputValue].NumericByRef().s4 = pinValue;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
}

NANOCLR_NOCLEANUP();
}

HRESULT Library_sys_dev_gpio_native_System_Device_Gpio_GpioPin::Read(CLR_RT_HeapBlock *gpioPin, bool &pinValue)
{
GPIO_PIN pinNumber = (GPIO_PIN)gpioPin[FIELD___pinNumber].NumericByRefConst().s4;

pinValue = CPU_GPIO_GetPinState(pinNumber);

return S_OK;
}

0 comments on commit fcec675

Please sign in to comment.