⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2cclass.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
//  Use of this source code is subject to the terms of the Microsoft end-user
//  license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
//  If you did not accept the terms of the EULA, you are not authorized to use
//  this source code. For a copy of the EULA, please see the LICENSE.RTF on your
//  install media.
//
//------------------------------------------------------------------------------
//
//  File:  i2cclass.c
//
//  This file contains the main I2C protocol engine class.
//
//------------------------------------------------------------------------------

#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <linklist.h>
#include <windev.h>
#include <stdlib.h>
#include "mxarm11.h"
#include "i2cbus.h"
#include "i2cclass.h"

//------------------------------------------------------------------------------
// External Functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// External Variables 
//------------------------------------------------------------------------------

// I2C_IOControl Critical Section
extern CRITICAL_SECTION gcsI2CIOControlLock;
CRITICAL_SECTION gcsI2CBusLock;

//------------------------------------------------------------------------------
// Defines 
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Global Variables 
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Local Variables 
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------

//-----------------------------------------------------------------------------
//
// Function: I2CClass::I2CClass
//
// This I2CClass constructor creates all the mutexes, events and heaps required
// for the subsequent use of I2C bus interface. It will also allocate the
// interrupt id from the HAL and binds the interrupt event to the interrupt id.
// This constructor has a built-in mechanism to prevent concurrent execution and a
// multiple interrupt binding procedure.
//
// Parameters:
//  None.
//
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------

I2CClass::I2CClass(UINT32 index)
{
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass +\r\n")));

    m_iModuleIndex = index;

    // Mapped I2C Register Base Physical Address -> Virtual Address +
    {
        PHYSICAL_ADDRESS phyAddr;

        // Copy I2C physical address
        phyAddr.QuadPart = I2CGetBaseRegAddr(m_iModuleIndex);
        // Map to virtual address
        pI2CReg = (PCSP_I2C_REG) MmMapIoSpace(phyAddr, sizeof(CSP_I2C_REG), FALSE);

        // If mapping fails, fatal error, quit
        if (pI2CReg == NULL)
        {
            DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("I2CClass::I2CClass:MmMapIoSpace(): Failed! ErrCode=%d \r\n"), GetLastError()));
            iResult = I2C_ERR_PA_VA_MISSING;
            return;
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:MmMapIoSpace(): pI2CReg=0x%x \r\n"), pI2CReg));

    // Create Hardware Interrupt Occurrence Event
    {
        hInterrupted = CreateEvent(NULL, FALSE, FALSE, NULL);
        // Able to create or obtain the event?
        if (hInterrupted == NULL)
        {
            DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("I2CClass::I2CClass:CreateEvent(): Interrupt Occurrence Event (hardware) Failed! ErrCode=%d \r\n"), GetLastError()));
            iResult = I2C_ERR_EOPS_CREATE;
            return;
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:CreateEvent(): hInterrupted=0x%x \r\n"), hInterrupted));

    // Create Software Interrupt Event (to obviate priority inversion bugs)
    {
        m_hI2CIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
        // Able to create or obtain the event?
        if (m_hI2CIntrEvent == NULL)
        {
            DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("I2CClass::I2CClass:CreateEvent(): Interrupt Occurrence Event (software) Failed! ErrCode=%d \r\n"), GetLastError()));
            iResult = I2C_ERR_EOPS_CREATE;
            return;
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:CreateEvent(): m_hI2CIntrEvent=0x%x \r\n"), m_hI2CIntrEvent));

    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:InitializeCriticalSection(): Creating I2C_IOControl Critical Section! \r\n")));

    // I2C_IOControl Critical Section
    {
        InitializeCriticalSection(&gcsI2CIOControlLock);
    }

    // Configure IOMUX for I2C pins
    {
        if (!BSPI2CIOMUXConfig(m_iModuleIndex))
        {
            DEBUGMSG(ZONE_ERROR, 
                (TEXT("%s: Error configuring IOMUX for I2C.\r\n"), __WFUNCTION__));
            return;
        }
    }

    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:InitializeCriticalSection(): Creating I2C Bus Critical Section! \r\n")));

    // I2C Bus Critical Section
    {
        InitializeCriticalSection(&gcsI2CBusLock);
    }

    // Map IRQ -> System Interrupt ID
    {
        // Copy our I2C IRQ Number
        DWORD dwIrq = I2CGetIRQ(m_iModuleIndex);

        // Get kernel to translate IRQ -> System Interrupt ID
        if (!KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &dwIrq, sizeof(DWORD), &dwSysIntr, sizeof(DWORD), NULL))
        {
            DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("I2CClass::I2CClass:KernelIoControl(): IRQ -> SysIntr Failed! ErrCode=%d \r\n"), GetLastError()));
            iResult = I2C_ERR_IRQ_SYSINTR_MISSING;
            return;
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:KernelIoControl(): dwSysIntr=0x%x \r\n"), dwSysIntr));

    // Link hInterrupted -> I2C Interrupt Pin
    {
        if (!InterruptInitialize(dwSysIntr, hInterrupted, NULL, 0))
        {
            DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("I2CClass::I2CClass:Interruptinitialize(): Linking failed! ErrCode=%d \r\n"), GetLastError()));
            iResult = I2C_ERR_INT_INIT;
            return;
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:Interruptinitialize(): Linking passed! \r\n")));

    // Get BSP interrupt wait timeout value
    {
        iIntrWaitTimeout = BSPGetTimeoutValue();
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:BSPGetTimeoutValue(): Timeout retrieved! \r\n")));


    // Create IST thread to receive hardware interrupts
    {
        // Start I2C IST thread
        // Initialize thread for I2C interrupt handling
        //      pThreadAttributes = NULL (must be NULL)
        //      dwStackSize = 0 => default stack size determined by linker
        //      lpStartAddress = I2CIST => thread entry point
        //      lpParameter = this => point to thread parameter
        //      dwCreationFlags = 0 => no flags
        //      lpThreadId = NULL => thread ID is not returned
        m_hI2CIST = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)I2CIST, this, 0, NULL);

        if (m_hI2CIST == NULL)
        {
            DEBUGMSG(ZONE_INIT,(TEXT("%s: CreateThread failed!\r\n"), __WFUNCTION__));
            iResult = I2C_ERR_INT_INIT;
            return;
        }
        else
        {
            DEBUGMSG(ZONE_INIT, (TEXT("%s: create I2C IST thread success\r\n"), __WFUNCTION__));
            CeSetThreadPriority(m_hI2CIST, 100);//THREAD_PRIORITY_TIME_CRITICAL);
        }
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:BSPGetTimeoutValue(): Timeout retrieved! \r\n")));
    

    // Disable I2C Module Initially
    {
       OUTREG16(&pI2CReg->I2CR, 0);
    }
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass:I2C_WORD_OUT(): I2CR=0x0 \r\n")));

    // Initialize I2C Mode
    byLastMode = I2C_MASTER_MODE;
    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass: Default to Master Mode \r\n")));

    // After this point, all initialization routines completed
    iResult = I2C_NO_ERROR;

    DEBUGMSG(ZONE_INIT, (TEXT("I2CClass::I2CClass -\r\n")));
}

//-----------------------------------------------------------------------------
//
// Function: I2CClass::~I2CClass
//
// This I2CClass destructor releases all the mutexes, events and heaps created.
// It will also attempt to terminate the worker thread. It has built-in 
// mechanism to determine whether it is safe to unbind the interrupt event from
// the interrupt id. This is to facilitate situations where multiple
// processes have obtained the same file handle to the I2C Bus Interface.
//
// Parameters:
//  None.
//
// Returns:  
//      None.
//
//-----------------------------------------------------------------------------
    
I2CClass::~I2CClass(void)
{
    DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass +\r\n")));

    // Release the interrupt resources
    InterruptDisable(dwSysIntr);
    DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass: Release System Interrupt \r\n")));

    // Kill interrupt service thread
    if (m_hI2CIST)
    {
        TerminateThread(m_hI2CIST, 0);
        CloseHandle(m_hI2CIST);
        m_hI2CIST = NULL;
    }

    CloseHandle(hInterrupted);
    // Prevent the later sections from thinking it is still valid
    hInterrupted = NULL;

    CloseHandle(m_hI2CIntrEvent);
    // Prevent the later sections from thinking it is still valid
    m_hI2CIntrEvent = NULL;

    // Release the interrupt
    DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass(): Releasing dwSysIntr = 0x%x \r\n"), dwSysIntr));
    if (!KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &dwSysIntr, sizeof(DWORD), NULL, 0, NULL))
        DEBUGMSG(ZONE_DEINIT | ZONE_ERROR, (TEXT("ERROR: Failed to release dwSysIntr.\r\n")));                

    // I2C_IOControl Critical Section
    {
        DeleteCriticalSection(&gcsI2CIOControlLock);
    }

    DEBUGMSG(ZONE_DEINIT, (TEXT("I2CClass::~I2CClass:DeleteCriticalSection(): Deleting I2C_IOControl Critical Section! \r\n")));

    // I2C Bus Critical Section
    {
        DeleteCriticalSection(&gcsI2CBusLock);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -