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

📄 xsac97ctrl.c

📁 嵌入式系统关于串口传输、触摸屏、定时器、控制器、中断处理、音频控制等实验代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        
        if (status != ERR_NONE)    
        {  
        	PrintfUartDef("!!!!Error Cold reset AC97\r\n");
			status = ERR_T_SW_INTERNAL;
        }
        else 
        	PrintfUartDef("AC97 Cold reset OK ....\r\n");

        // Note: this system has only one codec.  For systems with a primary and 
        //  secondary device, the identity of a device that did not properly
        //  reset could be ascertained at this point.
    }
   
    //must delay, to let controller settle
    Util_DelayMs(500);
    
    if (status)
    {
        if ((ERR_T_NOBITSET != status) && (ERR_T_TIMEOUT != status))
        {
            // Other errors indicate a bad parameter, failure to clear any
            //    existing handler by the interrupt controller driver, or 
            //    violation of the assumption that the AC'97 is unused by a 
            //    debugger.  All are essentially software errors.
            // The error log, as filled in by the subroutines, should leave a 
            //    trace of exactly what the problem was.

            status = ERR_T_SW_INTERNAL;
        }
//        LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL, 
//            ERR_S_XSAC97CTRL_HWSETUP, status, 0, 0, 0)
    }

    return (status);

} // End XsAc97CtrlHWSetup ()    



/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlGetStatus 
*
* DESCRIPTION:      Reports the value of the specified status indicator, as
*                   obtained from the ACUNIT's GSR register.  Clears the
*                   status indicator, if possible, after reading it.
*
*                   Should not be used for status types that are currently in 
*                   use as interrupt triggers.
*
* INPUT PARAMETERS: XsAc97CtrlStatusIdT statusId: ID of status indicator to get
*
* RETURNS:    Status indicator masked and normalized to bit 0. 
*             Invalid ID: 0 (There is no direct reporting of invalid ID error).
*
* GLOBAL EFFECTS:   1) Because the status indicator is cleared, it will not be 
*                       available to trigger an interrupt.
*                   2) If the specified status ID is invalid, an error is 
*                       logged in the error log and the context structure.
*
* ASSUMPTIONS:      We don't have to double-check the hardware by making sure
*                   that a clearable status actually cleared.
*
* CALLS:            
*
* CALLED BY:        
*
* PROTOTYPE:        UINT32 XsAc97CtrlGetStatus (XsAc97CtrlStatusIdT);
*
*******************************************************************************
*/

UINT32 XsAc97CtrlGetStatus (XsAc97CtrlStatusIdT statusId)
{
    UINT32                  statusIndication = 0;  // Assume bad ID
    UINT32                  rangeCheckResult;
    XsAc97CtrlStatusEntryT* statusTableEntryP;


    rangeCheckResult = XsAc97CtrlRangeCheckStatusId (statusId);

    if (rangeCheckResult)
    {
//        LOGERROR ( XsAc97CtrlContext.loggedError, 
//            ERR_L_XSAC97CTRL,
 //           ERR_S_XSAC97CTRL_GET_STATUS,
  //          rangeCheckResult, 0, 0, 0)
    }
    else
    {
        statusTableEntryP = XsAc97CtrlStatusTable + statusId;

        // Get the indication, normalize it, then isolate it.
        statusIndication   = XsAc97CtrlRegsP->GSR;
        statusIndication >>= statusTableEntryP->reportBitShiftGsr;
        statusIndication  &= statusTableEntryP->reportBitMaskGsr;

        // Clear the indication if it exists and can be cleared.  
        //  Don't use the clearing subroutine, there's so much extra overhead.
        // Don't clear without finding it, to avoid race condition.
        // NULL clear register means it can't be cleared.
        if (statusIndication && statusTableEntryP->clearRegisterP)
        {   
            //  Write a shifted "1" to clear the status.  Don't "OR" it in.
            *statusTableEntryP->clearRegisterP = 
                1u << statusTableEntryP->clearBitShift;
        }
    }  // else (rangeCheckResult)

    return (statusIndication);

} // XsAc97CtrlGetStatus()


/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlWriteCodecReg
*
* DESCRIPTION:      Write a value to a specific mixer register in a specific 
*                   AC'97 codec or modem, using the AC Link.
*
* INPUT PARAMETERS: 
*
* RETURNS:          
*       Success:    0 (ERR_NONE)
*       Failure:    ERR_T_NOT_AVAIL: AC Link was not available within the 
*                           timeout interval.
*                   ERR_T_ILLPARAM:  One of the ID parameters was illegal.
*                           Which one is recorded in the first parameter of
*                           the logged error.  Software error.
*
* GLOBAL EFFECTS:   Disables interrupts briefly, possibly sub-microsecond.
*                     Theoretical maximum is about 130 - 200 uSec.
*                   On termination, AC Link remains locked until the codec I/0
*                     cycle initiated by the local write completes.  That 
*                     should take from 21 to 42 uSec.  Next codec I/O will not
*                     be able to start during that time.
*
* ASSUMPTIONS:      
*
* CALLS:            
*
* CALLED BY:        
*
* PROTOTYPE:        UINT32 XsAc97CtrlWriteCodecReg (XsAc97CtrlCodecModemIdT, 
*                                                  AC97MixerRegisterIdT,
*                                                  UINT32);
*
*******************************************************************************
*
* DESIGN:
*
*  1.  Disable interrupts, saving pre-existing state.
*  2.  Read the CAR until it is verified that no Codec I/O accesses are 
*        currently in progress.  This also claims the next codec I/O transaction
*        for this operation.
*  3.  Clear any status and error indications that can result from a Codec 
*        write operation (CDONE).
*  4.  Write the specified data to the processor memory location that is mapped
*        to the target Codec's target register.
*  5.  Restore previous interrupt state.
*
*  Note that this operation does not wait for the transmission to complete.  
*    Any remaining wait is done in the beginning of the next access.
* 
*******************************************************************************
*/

UINT32 XsAc97CtrlWriteCodecReg   (XsAc97CtrlCodecModemIdT  ac97DeviceId, 
                                 AC97MixerRegisterIdT     targetRegister,
                                 UINT32                   newValue)
{
    UINT32    status ;
    INT       badParamNum  = 0 ; // Which param had error.  Assume no errors.
    BOOL      gotLink;
    UINT32    irqIntState;
    INT       timeRemaining;
    VUINT32*  mixerRegsAccessP;
    VUINT     finishedStatus;

    status = Ac97CheckRegId (targetRegister);
    if (status)
    {
        badParamNum = 2;
    }
    else    // register ID OK, set register access pointer to codec access base
    {
        switch (ac97DeviceId)
        {
            case XS_AC97CTRL_CM_ID_PRI_CODEC:
                mixerRegsAccessP  = &XsAc97CtrlRegsP->
                XsAC97CtrlMixerRegsPrimaryAud[0];
                break;
            default:
                status      = ERR_T_ILLPARAM;
                badParamNum = 1;
                break;
        }
    } // else (register ID OK)

    if (!status)
    {
        // Point to specified register within area mapped to target codec regs
        mixerRegsAccessP += (targetRegister / XS_AC97CTRL_MIXER_REGS_PER_WORD);

        irqIntState = XsIcDisableInterruptsIrq();

        // Lock the ACLINK
        timeRemaining = XS_AC97CTRL_CAIP_TIMEOUT_1USECS;
        do
        {
            gotLink = XsAc97CtrlLockAcLink();
            if (!gotLink)    // 1 usec is a long time.  Skip delay if possible.
            {
                DM_WaitUs(1);
            }
        }
        // Wait while time remaining and ACLINK not available
        while ( timeRemaining-- && !gotLink );

        if (!gotLink) // Didn't get the ACLINK
        {
            status = ERR_T_NOT_AVAIL;      
        }
        else  // We got the link.  Perform the write operation and don't wait.
        {
            // First, clear old write status indications.
            // Ignore return code; if the ID is invalid, it won't compile.
            (void) XsAc97CtrlClearStatus (XS_AC97CTRL_STAT_CDONE); 

            *mixerRegsAccessP = newValue;       // Now the write!

            // Wait until write cycle is complete.  There should be a way
            //  to do this speculatively at the beginning of the procedure.
            //  Need to discover it.  Too inefficient to always wait.

            // Use more forgiving read timeout
            timeRemaining = XS_AC97CTRL_READ_TIMEOUT_1USECS;
            do
            {
                DM_WaitUs(1);
                finishedStatus = 
                    XsAc97CtrlGetStatus (XS_AC97CTRL_STAT_CDONE);
            }
            // Wait while time remaining and command I/O still incomplete
            // CDONE bit is high when done.
            while (   (timeRemaining--) && !finishedStatus);

        }  // Got AC link

        XsIcRestoreInterruptsIrq (irqIntState);

    }  // if (!status): No problem with params.  Sent command if link available.

    if (status)
    {
//        LOGERROR (XsAc97CtrlContext.loggedError, ERR_L_XSAC97CTRL, 
 //           ERR_S_XSAC97CTRL_CODEC_WRITE, status, badParamNum, 0, targetRegister)
    }

    return(status);

} // XsAc97CtrlCodecWrite()   


/*
*******************************************************************************
*
* FUNCTION:         XsAc97CtrlReadCodecReg
*
* DESCRIPTION:      Read the value of a specific mixer register in a specified 
*                   AC'97 codec or modem, using the AC Link.
*
* INPUT PARAMETERS: 
*       XsAc97CtrlCodecModemIdT ac97DeviceId: ID of modem or codec to read.
*       AC97MixerRegisterIdT  targetRegister: ID of register on codec.
*       UINT32*               mixerRegValueP: Address of variable in which to 
*                                             put the value from the codec reg.
*
* OUTPUT: UINT32* mixerRegValueP: Receives the value reported for the 
*                                   specified mixer register in the specified
*                                   codec.  Valid only if return code is zero.
*
* RETURNS:          
*       Success:    0 (ERR_NONE); value in *mixerRegValueP is valid.
*       Failure:    ERR_T_NOT_AVAIL: AC Link was not available within the 
*                           initial timeout interval.
*                   ERR_T_ILLPARAM:  One of the ID parameters was illegal.
*                           Which one is recorded in the first parameter of
*                           the logged error.  Software error.
*                   ERR_T_TIMEOUT:   A timeout occurred after initial 
*                           acquisition of the AC Link.  The point in the 
*                           routine where the timeout occurred is recorded
*                           in the second parameter of the logged error.
*
* GLOBAL EFFECTS:   Disables interrupts for at least 42 uSec.  Theoretical 
*                     maximum is about 250 uSec.
*                   On termination, AC Link remains locked until the codec I/0
*                     cycle initiated by the second local read completes.  That
*                     could take from 42 to 84+ uSec.  Next codec I/O will not
*                     be able to start during that time.
*                   Errors recorded in context structure and system error log.
*
* ASSUMPTIONS:      
*
* CALLS:            
*
* CALLED BY:        
*
* PROTOTYPE:        UINT32 XsAc97CtrlReadCodecReg (XsAc97CtrlCodecModemIdT, 
*                                                  AC97MixerRegisterIdT, 
*                                                  UINT32*);
*
*******************************************************************************
*
* DESIGN:
* 
*  1.  Disable interrupts, saving pre-existing state.
*  2.  Read the CAR until it is verified that no codec I/O accesses are 
*      currently in progress.  This also claims the next codec I/O transaction 
*      for this operation.
*  3.  Clear any status and error indications that can result from a codec read
*      operation (SDONE, Read Completion Status).

⌨️ 快捷键说明

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