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

📄 复件 tmiic.c

📁 用于TM1300/PNX1300系列DSP(主要用于视频处理)的设备库的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  +-------------------------------------------------------------------+
 *  | Copyright (c) 1995,1996,1997 by TriMedia Technologies.            |
 *  |                                                                   |
 *  | This software  is furnished under a license  and may only be used |
 *  | and copied in accordance with the terms  and conditions of such a |
 *  | license  and with  the inclusion of this  copyright notice.  This |
 *  | software or any other copies of this software may not be provided |
 *  | or otherwise  made available  to any other person.  The ownership |
 *  | and title of this software is not transferred.                    |
 *  |                                                                   |
 *  | The information  in this software  is subject  to change  without |
 *  | any  prior notice  and should not be construed as a commitment by |
 *  | TriMedia Technologies.                                            |
 *  |                                                                   |
 *  | This  code  and  information  is  provided  "as is"  without  any |
 *  | warranty of any kind,  either expressed or implied, including but |
 *  | not limited  to the implied warranties  of merchantability and/or |
 *  | fitness for any particular purpose.                               |
 *  +-------------------------------------------------------------------+
 *
 *
 *  Module name              : tmIIC.c    1.68
 *
 *  Last update              : 19:33:12 - 00/11/09
 *
 *
 *  Description              :
 *
 *
 *  Revision                 : 
 *      
 */

/*----------------------------includes----------------------------------------*/

#include <stdio.h>
#include <tm1/tmAssert.h>
#include <tmlib/AppModel.h>
#include <tm1/mmio.h>
#include <tm1/tmIIC.h>
#include <tm1/tmInterrupts.h>
#include <tm1/tmProcessor.h>
#include <tm1/tmIICS.h>
#include <tm1/tmIICmmio.h>

#include <tmlib/dprintf.h>     /* for debugging with DP(()) */
#define IIC_DP(x)

/*------------------------- local definitions --------------------------------*/

/* normally, these come from the Makefile */
#ifndef MAJOR_VERSION
#define MAJOR_VERSION   3
#endif
#ifndef MINOR_VERSION
#define MINOR_VERSION   0
#endif
#ifndef BUILD_VERSION
#define BUILD_VERSION   0
#endif

 
/*
 * This macro determines the inclusion of code that detects
 * if we're running on a TM1000 so it can wait endlessly 
 * before/after doing anything
 */

#define TM1000_COMPATIBLE           1

/*
 * Default settings for iicReadReg/iicWriteReg
 */
  
#define MAX_NUM_RETRIES             10
#define TM1100_SLEEP_BEFORE_RETRY   50

/*
 * Wait before timeout in case of Synchronous_by_polling
 */
 
#define MAX_WAIT_IN_US              50000

/* 
 * Largest number of bytes to transfer in one request
 */

#define LARGEST_TRANSFER            0xfe

/*----------------------------globals---------------------------------------*/

/* 
 * Keep queue of waiting requests
 */

static piicRequest_t iic_queue_first = Null;
static piicRequest_t iic_queue_last  = Null;

/* 
 * Keep pointer to the transfer currently being executed.
 */

static piicRequest_t iic_current_request;

/* 
 * Keep some info that is shared over ISRs:
 * - Whether we just did a write of a subaddress to do a subaddress read
 * - Where we want to read the buffer in case of a subaddress read
 * - The number of times we retried this request already.
 */

static Bool   SubaddressRead = False;
static UInt32 AddressRegister;
static Int    NumRetries = 0;
static volatile UInt LoopCount;

/*
 * Default libdev variables
 */

static Int  next_instance = 0;
static iicSetup_t IICSetup = {intPRIO_5};

static iicCapabilities_t capabilities =
{
     /* version                */ {MAJOR_VERSION, MINOR_VERSION, BUILD_VERSION},
     /* numSupportedInstances  */ -1,
     /* numCurrentInstances    */ 0,
     /* largestTransfer        */ LARGEST_TRANSFER
};

/*----------------------------HW-weirdness---------------------------------*/

static   pprocCapabilities_t procCap = Null;
static   Bool  TM1100_1_2; 

/*----------------------------TM1000---------------------------------------*/

/*
 * Values we only need to workaround tm1000 hw bugs
 */

#if TM1000_COMPATIBLE

#define  TM1000_SLEEP_BEFORE_WRITE     600 /* workaround for hw bugsw */
static   Bool  TM1000; 

#endif

/*----------------------------TM2000---------------------------------------*/

void*       _iicsISR  = Null;
UInt32      _iicsMask = 0;

/*----------------------------macros---------------------------------------*/

/* 
 * Copy max 4 bytes into the data field of request r 
 */

#define COPY_IN(r, d) {                                        \
            int i;                                             \
            for (i = 3; i >= 0 && (r)->index < (r)->byteCount; \
                 i--, (r)->index++)                            \
                (r)->data[(r)->index] = ((d)>>i*8) & 0xff ;    \
            }
            
/* 
 * Copy max 4 bytes out of the data field of request r into d
 */
 
#define COPY_OUT(r, d)                            \
            *(d) = (r)->data[(r)->index  ]<<24  | \
                   (r)->data[(r)->index+1]<<16  | \
                   (r)->data[(r)->index+2]<<8   | \
                   (r)->data[(r)->index+3] ;      \
            (r)->index += 4;                   

/* 
 * Copy max 4 bytes out of the data field of request r into d
 * If sub then make sure the lm byte is the subaddress.
 */
 
#define COPY_OUT_SUB(r, d, sub)                        \
            if (sub) {                                 \
                *(d) = (r)->subaddress        <<24  |  \
                       (r)->data[(r)->index  ]<<16  |  \
                       (r)->data[(r)->index+1]<<8   |  \
                       (r)->data[(r)->index+2] ;       \
                (r)->index += 3;                       \
            } else {                                   \
                COPY_OUT((r), (d));                    \
            }




/*----------------------------local-functions---------------------------------*/

static void 
start_next_transfer(Bool retry)  
{                                                          
    UInt32 data;  
    UInt8 byteCount = iic_current_request->byteCount;
    Bool subaddress_write = False;
    UInt8 address = iic_current_request->address;
    
    IIC_DP(("start_next_transfer, %x\n", iic_current_request));
    
    if (!retry) {
    
        NumRetries = 0;
        
    } else {
        
        intSET_IEN();
        microsleep(iic_current_request->waitBeforeRetry);
        intCLEAR_IEN();
    }
              
    if (iic_current_request->type == IIC_SUBADDRESS || iic_current_request->direction == IIC_WRITE) {

#if TM1000_COMPATIBLE    
        if (TM1000) {
            intSET_IEN();
            microsleep(TM1000_SLEEP_BEFORE_WRITE);
            intCLEAR_IEN();
        }
#endif

    }
    
    LoopCount = 0;

    if (iic_current_request->type == IIC_SUBADDRESS) {
        if (iic_current_request->direction == IIC_READ) {
                    
            /* 
             * In case of a subaddress read, write the sub address and 
             * flag the fact that you need to read in the ISR
             */
            
            SubaddressRead  = True;
            AddressRegister = (iic_current_request->address << 24) | (byteCount << 8);
                        
            MMIO(IIC_CTL)   = IIC_CLR_ALL | IIC_GD_IEN | IIC_FIEN |
                              IIC_ANIEN | IIC_DNIEN  | IIC_ENABLE;  
            MMIO(IIC_AR)    = ((address & 0xFE) << 24) | (1 << 8); 
            MMIO(IIC_DR)    = iic_current_request->subaddress << 24;

            
            return;
                    
        } else {
        
            /* 
             * In case of a subaddress write, write one extra byte
             * holding the subaddress
             */
             
            subaddress_write = True;
            byteCount++;
           
        }   
    }                                               

#if TM1000_COMPATIBLE    
    if (TM1000 && iic_current_request->direction == IIC_WRITE) {
        byteCount++;   /* workaround HW bug */
    } 
#endif
    
    MMIO(IIC_CTL) = IIC_CLR_ALL | IIC_GD_IEN | IIC_FIEN |
                    IIC_ANIEN | IIC_DNIEN  | IIC_ENABLE;  
    MMIO(IIC_AR)  = (address << 24) | (byteCount << 8); 
    
    if (iic_current_request->direction == IIC_WRITE) {                                            
        COPY_OUT_SUB(iic_current_request, &data, subaddress_write);             
        MMIO(IIC_DR) = data;                                                              
    }                 
                                                                        
}




static void 
_iic_handler(void)
{
    UInt32 data, status, acker=0;
    
    status = MMIO(IIC_STATUS);

    /*
     * Check the four bits in the status register that need 
     * to be cleared. Clearing is done 6 bits to the right,
     * in the control register. See Databook Figure 15-2.
     */ 

    acker = (status & 0xf0000000) >> 6;
        
    MMIO(IIC_CTL) |= acker;
    
    /* 
     * If we are running on a TM2 we have to check for 
     * IICS interrupts as well, and call the iicsISR if
     * needed.
     */

    if ((status & _iicsMask) && (_iicsISR != Null)) {
        ((iicsFunc_t)_iicsISR)(status);
    }


    /* 
     * On an error interrupt, retry, or fall thru, so that
     * the done flag is set and the requester is resumed.
     */

    if (iicANACK(status) || iicDNACK(status)) {
            
        if (++NumRetries <= iic_current_request->numRetries) {
                             
            iic_current_request->index = 0;
            
            start_next_transfer(True);  /* starts iic_current_request, retry */
            
            return;
        }

        if (iicANACK(status)) {
            iic_current_request->errorCode |= IIC_ERR_ADDRESS_NACK;
        } else {
            iic_current_request->errorCode |= IIC_ERR_DATA_NACK;
        }            
    }
     
    /*
     * When we get an FI, we have to read the data from or put new
     * data into the data register.
     * If we just wrote a Subaddress to a slave, we know we will not
     * do anything.
     */

    if (iicFI(status) || iicGDI(status) ) {
                
        if (!SubaddressRead) {
        
            if (iic_current_request->direction == IIC_READ) {

                data = MMIO(IIC_DR);
                COPY_IN(iic_current_request, data);    

            } else if (iic_current_request->byteCount + (iic_current_request->type==IIC_SUBADDRESS?1:0) > iic_current_request->index) {

                COPY_OUT(iic_current_request, &data);            
                MMIO(IIC_DR) = data;

            } 
        }
    } 
    
    /*
     * On a GDI we know we are done 
     */
 
    if (iicGDI(status) || iicANACK(status) || iicDNACK(status)) {
        
        piicRequest_t     current             = iic_current_request;

        if (iicGDI(status)) {
            if (SubaddressRead) {
                
                SubaddressRead = False;
                                
                /*
                 * Start up the read of the subaddress now the
                 * the subaddress is written to the slave.
                 */
                                                 
                MMIO(IIC_CTL) = IIC_CLR_ALL | IIC_GD_IEN | IIC_FIEN | 
                                IIC_ANIEN | IIC_DNIEN  | IIC_ENABLE;                                      
                MMIO(IIC_AR)  = AddressRegister; 

                return;
                
            } 
        }
        
        /* 
         * Done with current transaction, or current transaction failed:
         * - set done flag, to wake up polling tasks
         * - start a next transaction, if any
         * - resume synchronous waiting tasks
         * - call completion function
         */
        
        iic_current_request   = iic_queue_first;
        current->done = True;
        IIC_DP(("Completed iic %x\n", current));
        
        if (iic_current_request != Null) 
        {
            iic_queue_first = iic_queue_first->link;
            
            if (iic_queue_first == Null) {
                iic_queue_last = Null;
            } 
            start_next_transfer(False); /* starts iic_current_request, no retries */
        }
        
        if (current->mode == IIC_Synchronous) {
            AppModel_resume(current->requester);
        }  
                
        if (current->completion_function) {
            IIC_DP(("Completion func of %x\n", current));
            current->completion_function(current);
        }
        
    }
}

static void iic_handler(void)
{
#pragma TCS_handler
    AppModel_suspend_scheduling();
    AppModel_run_on_sstack((AppModel_Fun)_iic_handler, Null);
    AppModel_resume_scheduling();
}

/*----------------------------functions---------------------------------------*/

extern tmLibdevErr_t 
iicWriteReg(UInt address, Int subaddress, UInt value)
{
    Int instance = 0;
    iicRequest_t req;
    tmLibdevErr_t err;
    UInt8 data = value;
        
    if (err = iicOpen(&instance))
        return err;
    
    req.direction           = IIC_WRITE;
    req.byteCount           = 1;
    req.address             = address;
    req.subaddress          = subaddress;
    req.numRetries          = MAX_NUM_RETRIES;
    req.waitBeforeRetry     = TM1100_SLEEP_BEFORE_RETRY;
    req.data                = &data;
    req.mode                = IIC_Synchronous_By_Polling;
    req.type                = (subaddress < 0) ? IIC_SIMPLE : IIC_SUBADDRESS;
    req.completion_function = Null;

    err  = iicDispatch(instance, &req);
        
    err |= iicClose(instance);
    
    return err;
}

extern tmLibdevErr_t 
iicReadReg(UInt address, Int subaddress, UInt * value)
{
    Int instance = 0;
    iicRequest_t req;
    tmLibdevErr_t err;
    UInt8 data;
        
    if (err = iicOpen(&instance))
        return err;
            

⌨️ 快捷键说明

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