HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::Dispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) { TINYCLR_HEADER(); { CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); CLR_RT_HeapBlock_NativeEventDispatcher* port; TINYCLR_CHECK_HRESULT(Library_spot_hardware_native_Microsoft_SPOT_Hardware_NativeEventDispatcher::GetEventDispatcher( stack, port )); // Check if HW port was not closed. - if ( ( pThis[ FIELD__m_flags ].NumericByRefConst().s4 & GPIO_PortParams::c_Disposed ) == 0 ) { CLR_UINT32 portID = pThis[ FIELD__m_portId ].NumericByRefConst().u4; // Cleanup the HAL queue from the instance of assiciated CLR_RT_HeapBlock_NativeEventDispatcher port->RemoveFromHALQueue(); // Set flag in managed object that port is closed. pThis[ FIELD__m_flags ].NumericByRef().s4 |= GPIO_PortParams::c_Disposed; // Set pin to input state so the pin is in "weak" state and does not drain power. ::CPU_GPIO_EnableInputPin2( portID, false, NULL, 0, GPIO_INT_NONE, RESISTOR_PULLUP ); // Releases the pin ::CPU_GPIO_ReservePin( portID, FALSE ); } } TINYCLR_NOCLEANUP(); }
HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_NativeEventDispatcher::Dispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) { TINYCLR_HEADER(); CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); TINYCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); // Cleanup the HAL queue from the instance of assiciated CLR_RT_HeapBlock_NativeEventDispatcher pNativeDisp->RemoveFromHALQueue(); // Calls driver to de-initilaze hardware. TINYCLR_CHECK_HRESULT(pNativeDisp->m_DriverMethods->m_CleanupProc( pNativeDisp )); TINYCLR_NOCLEANUP(); }
HRESULT CLR_HW_Hardware::SpawnDispatcher() { NATIVE_PROFILE_CLR_HARDWARE(); TINYCLR_HEADER(); CLR_RT_ApplicationInterrupt* interrupt; CLR_RT_HeapBlock_NativeEventDispatcher* ioPort; CLR_RT_HeapBlock_NativeEventDispatcher ::InterruptPortInterrupt *interruptData; // if reboot is in progress, just bail out if(CLR_EE_DBG_IS( RebootPending )) { return S_OK; } interrupt = (CLR_RT_ApplicationInterrupt*)m_interruptData.m_applicationQueue.FirstValidNode(); if((interrupt == NULL) || !g_CLR_RT_ExecutionEngine.EnsureSystemThread( g_CLR_RT_ExecutionEngine.m_interruptThread, ThreadPriority::System_Highest )) { return S_OK; } interrupt->Unlink(); interruptData = &interrupt->m_interruptPortInterrupt; ioPort = interruptData->m_context; CLR_RT_ProtectFromGC gc1 ( *ioPort ); TINYCLR_SET_AND_LEAVE(ioPort->StartDispatch( interrupt, g_CLR_RT_ExecutionEngine.m_interruptThread )); TINYCLR_CLEANUP(); if(FAILED(hr)) { ioPort->ThreadTerminationCallback( interrupt ); } --m_interruptData.m_queuedInterrupts; TINYCLR_CLEANUP_END(); }
HRESULT Library_spot_hardware_native_Microsoft_SPOT_Hardware_NativeEventDispatcher::Dispose___VOID__BOOLEAN( CLR_RT_StackFrame& stack ) { TINYCLR_HEADER(); CLR_RT_HeapBlock_NativeEventDispatcher *pNativeDisp = NULL; CLR_RT_HeapBlock* pThis = stack.This(); FAULT_ON_NULL(pThis); TINYCLR_CHECK_HRESULT(GetEventDispatcher( stack, pNativeDisp )); // Cleanup the HAL queue from the instance of assiciated CLR_RT_HeapBlock_NativeEventDispatcher pNativeDisp->RemoveFromHALQueue(); // Calls driver to enable interrupts. Consider that there could be no driver // associated to this object so check that the driver methods are set // we will be tolerant in this case and not throw any exception if(pNativeDisp->m_DriverMethods != NULL) { TINYCLR_CHECK_HRESULT(pNativeDisp->m_DriverMethods->m_CleanupProc( pNativeDisp )); } TINYCLR_NOCLEANUP(); }
void Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::IsrProcedure( GPIO_PIN pin, BOOL pinState, void* context ) { { ASSERT_IRQ_MUST_BE_OFF(); // If context parameter is NULL, then there is no way to dispatch data managed thread. CLR_RT_HeapBlock_NativeEventDispatcher* port = (CLR_RT_HeapBlock_NativeEventDispatcher*)context; if ( port == NULL ) { return; } // Retrieve managed object correspoinding to instance of CLR_RT_HeapBlock. // Managed object keeps all the data associated with port. CLR_RT_HeapBlock* pManagedPortObj = NULL; port->RecoverManagedObject( pManagedPortObj ); if ( pManagedPortObj == NULL ) { return; } CLR_INT32 &flags = pManagedPortObj[ Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::FIELD__m_flags ].NumericByRef().s4; CLR_UINT32 portID = pManagedPortObj[ Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::FIELD__m_portId ].NumericByRefConst().u4; GPIO_INT_EDGE interruptMode = (GPIO_INT_EDGE)pManagedPortObj[ Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::FIELD__m_interruptMode ].NumericByRefConst().s4; GPIO_RESISTOR resistorMode = (GPIO_RESISTOR)pManagedPortObj[ Library_spot_hardware_native_Microsoft_SPOT_Hardware_Port::FIELD__m_resistorMode ].NumericByRefConst().s4; // Discard the call if flags show that interrupt is disabled for this port. if ( flags & GPIO_PortParams::c_InterruptDisabled ) { return; } // For the level interrupt we disable it once the level was reached. // Application needs to enable it back. It is used to protect agains multiple callbacks as result of reaching the level. if ( interruptMode == GPIO_INT_LEVEL_HIGH || interruptMode == GPIO_INT_LEVEL_LOW ) { if ( flags & GPIO_PortParams::c_Disposed ) { return; } // Disable interrupts for port if not disabled. if(( flags & GPIO_PortParams::c_InterruptDisabled ) == 0) { // Disable level interrupt. flags |= GPIO_PortParams::c_InterruptDisabled; ::CPU_GPIO_EnableInputPin2( portID, // data1 is portId for GPIO case. false, NULL, 0, GPIO_INT_NONE, resistorMode ); } } // To calling SaveToHALQueue saves data to 128 slot HAL queue and finally causes dispatch to managed callback. port->SaveToHALQueue( pin, pinState ); } }