//------------------------------------------------------------------------------
/// Configures a TWI peripheral to operate in master mode, at the given
/// frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
/// \param pTwi  Pointer to an AT91S_TWI instance.
/// \param twck  Desired TWI clock frequency.
/// \param mck  Master clock frequency.
//------------------------------------------------------------------------------
void TWI_Configure(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck)
{
    unsigned int ckdiv = 0;
    unsigned int cldiv;
    unsigned char ok = 0;

    trace_LOG(trace_DEBUG, "-D- TWI_Configure()\n\r");
    SANITY_CHECK(pTwi);

    // Reset the TWI
    pTwi->TWI_CR = AT91C_TWI_SWRST;

    // Set master mode
    pTwi->TWI_CR = AT91C_TWI_MSEN;

    // Configure clock
    while (!ok) {
        
        cldiv = ((mck / (2 * twck)) - 3) / power(2, ckdiv);
        if (cldiv <= 255) {

            ok = 1;
        }
        else {

            ckdiv++;
        }
    }

    ASSERT(ckdiv < 8, "-F- Cannot find valid TWI clock parameters\n\r");
    trace_LOG(trace_INFO, "-D- Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", ckdiv, cldiv);
    pTwi->TWI_CWGR = (ckdiv << 16) | (cldiv << 8) | cldiv;
}
//------------------------------------------------------------------------------
/// Handles all interrupts on the given PIO controller.
/// \param id  PIO controller ID.
/// \param pBase  PIO controller base address.
//------------------------------------------------------------------------------
void PioInterruptHandler(unsigned int id, AT91S_PIO *pBase)
{
    unsigned int status;
    unsigned int i;

    // Check PIO controller status
    status = pBase->PIO_ISR;
    status &= pBase->PIO_IMR;
    if (status != 0) {

        trace_LOG(trace_DEBUG, "-D- PIO interrupt on PIO controller #%d\n\r", id);

        // Check all sources
        i = 0;
        while (status != 0) {

            // There cannot be an unconfigured source enabled.
            SANITY_CHECK(i < numSources);

            // Source if configured on PIOA
            if (pSources[i].pPin->id == id) {

                // Source has PIOs which have changed
                if ((status & pSources[i].pPin->mask) != 0) {

                    trace_LOG(trace_DEBUG, "-D- Interrupt source #%d triggered\n\r", i);

                    pSources[i].handler(pSources[i].pPin);
                    status &= ~(pSources[i].pPin->mask);
                }
            }
            i++;
        }
    }
}
Beispiel #3
0
//-----------------------------------------------------------------------------
/// Get the statstic information & reset it
/// \param pStats   Pointer to EmacStats structure to copy the informations
/// \param reset    Reset the statistics after copy it
//-----------------------------------------------------------------------------
void EMAC_GetStatistics(EmacStats *pStats, unsigned char reset)
{
    unsigned int ncrBackup = 0;

    trace_LOG(trace_DEBUG, "EMAC_GetStatistics\n\r");

    // Sanity check
    if (pStats == (EmacStats *) 0) {
        return;
    }

    ncrBackup = AT91C_BASE_EMAC->EMAC_NCR & (AT91C_EMAC_TE | AT91C_EMAC_RE);

    // Disable TX/RX
    AT91C_BASE_EMAC->EMAC_NCR = ncrBackup & ~(AT91C_EMAC_TE | AT91C_EMAC_RE);

    // Copy the informations
    memcpy(pStats, (void*)&EmacStatistics, sizeof(EmacStats));

    // Reset the statistics
    if (reset) {
        memset((void*)&EmacStatistics, 0x00, sizeof(EmacStats));
        AT91C_BASE_EMAC->EMAC_NCR = ncrBackup | AT91C_EMAC_CLRSTAT;
    }

    // restore NCR
    AT91C_BASE_EMAC->EMAC_NCR = ncrBackup;
}
//------------------------------------------------------------------------------
/// Disables a given interrupt source.
/// \param pPin  Interrupt source to disable.
//------------------------------------------------------------------------------
void PIO_DisableIt(const Pin *pPin)
{
    SANITY_CHECK(pPin);

    trace_LOG(trace_DEBUG, "-D- PIO_DisableIt()\n\r");

    pPin->pio->PIO_IDR = pPin->mask;
}
Beispiel #5
0
//------------------------------------------------------------------------------
/// Sets the input data to encrypt/decrypt using TDES.
/// \param pInput  Pointer to the 64-bits input data.
//------------------------------------------------------------------------------
void TDES_SetInputData(const unsigned int *pInput)
{
    trace_LOG(trace_DEBUG, "-D- TDES_SetInputData()\n\r");
    SANITY_CHECK(pInput);

    AT91C_BASE_TDES->TDES_IDATAxR[0] = pInput[0];
    AT91C_BASE_TDES->TDES_IDATAxR[1] = pInput[1];
}
Beispiel #6
0
//------------------------------------------------------------------------------
/// Stores the output data from the last TDES operation into the given 64-bits
/// buffers.
/// \param pOutput  Pointer to a 64-bits output buffer.
//------------------------------------------------------------------------------
void TDES_GetOutputData(unsigned int *pOutput)
{
    trace_LOG(trace_DEBUG, "-D- TDES_GetOutputData()\n\r");
    SANITY_CHECK(pOutput);

    pOutput[0] = AT91C_BASE_TDES->TDES_ODATAxR[0];
    pOutput[1] = AT91C_BASE_TDES->TDES_ODATAxR[1];
}
Beispiel #7
0
//------------------------------------------------------------------------------
/// Sets the initialization vector to use when the TDES algorithm is configured
/// in a chained block mode (CBC, CFB or OFB).
/// \param pVector  Pointer to the 64-bits vector.
//------------------------------------------------------------------------------
void TDES_SetVector(const unsigned int *pVector)
{
    trace_LOG(trace_DEBUG, "-D- TDES_SetVector()\n\r");
    SANITY_CHECK(pVector);

    AT91C_BASE_TDES->TDES_IVxR[0] = pVector[0];
    AT91C_BASE_TDES->TDES_IVxR[1] = pVector[1];
}
//------------------------------------------------------------------------------
/// Configures an interrupt source.
/// \param pPin  Interrupt source.
/// \param handler  Desired interrupt handler for the source.
//------------------------------------------------------------------------------
void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
{
    InterruptSource *pSource;

    trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt()\n\r");

    SANITY_CHECK(pPin);
    ASSERT(numSources < MAX_INTERRUPT_SOURCES,
           "-F- PIO_ConfigureIt: Increase MAX_INTERRUPT_SOURCES\n\r");

    // Define new source
    trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt: Defining new source #%d.\n\r", numSources);

    pSource = &(pSources[numSources]);
    pSource->pPin = pPin;
    pSource->handler = handler;
    numSources++;
}
Beispiel #9
0
//------------------------------------------------------------------------------
/// Sets the input data buffer to encrypt/decrypt when in PDC mode.
/// \param pInput  Pointer to the input data.
/// \param size  Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetInputBuffer(const unsigned int *pInput, unsigned int size)
{
    trace_LOG(trace_DEBUG, "-D- TDES_SetInputBuffer()\n\r");
    SANITY_CHECK(pInput);
    SANITY_CHECK((size > 0) && ((size % 8) == 0));

    AT91C_BASE_TDES->TDES_TPR = (unsigned int) pInput;
    AT91C_BASE_TDES->TDES_TCR = size / 4;
}
Beispiel #10
0
//------------------------------------------------------------------------------
/// Sets the output buffer which will receive the encrypted/decrypted data when
/// using the PDC.
/// \param pOutput  Pointer to the output data.
/// \param size  Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetOutputBuffer(unsigned int *pOutput, unsigned int size)
{
    trace_LOG(trace_DEBUG, "-D- TDES_SetOutputBuffer()\n\r");
    SANITY_CHECK(pOutput);
    SANITY_CHECK((size > 0) && ((size % 8) == 0));

    AT91C_BASE_TDES->TDES_RPR = (unsigned int) pOutput;
    AT91C_BASE_TDES->TDES_RCR = size / 4;
}
Beispiel #11
0
//------------------------------------------------------------------------------
/// Starts the encryption or decryption process if the TDES peripheral is
/// configured in manual or PDC mode.
//------------------------------------------------------------------------------
void TDES_Start(void)
{
    trace_LOG(trace_DEBUG, "-D- TDES_Start()\n\r");
    SANITY_CHECK(((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL)
                 || ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_PDC));

    // Manual mode
    if ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL) {

        AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START;
    }
    // PDC mode
    else {

        AT91C_BASE_TDES->TDES_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
    }
}
Beispiel #12
0
//-----------------------------------------------------------------------------
/// Write PHY register
/// Return 1 if successfully, 0 if timeout.
/// \param PhyAddress PHY Address
/// \param Address Register Address
/// \param Value Data to write ( Actually 16 bit data )
/// \param retry The retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
unsigned char EMAC_WritePhy(unsigned char PhyAddress,
                            unsigned char Address,
                            unsigned int  Value,
                            unsigned int  retry)
{
    AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
                              | (AT91C_EMAC_CODE & (2 << 16))
                              | (AT91C_EMAC_RW & (1 << 28))
                              | (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
                              | (AT91C_EMAC_REGA & (Address << 18))
                              | (AT91C_EMAC_DATA & Value) ;
    if ( EMAC_WaitPhy(retry) == 0 ) {

        trace_LOG(trace_ERROR, "TimeOut EMAC_WritePhy\n\r");
        return 0;
    }
    return 1;
}
Beispiel #13
0
//------------------------------------------------------------------------------
/// Sets the 64-bits keys (one, two or three depending on the configuration)
/// that shall be used by the TDES algorithm.
/// \param pKey1  Pointer to key #1.
/// \param pKey2  Pointer to key #2 (shall be 0 in single-DES mode).
/// \param pKey3  Pointer to key #3 (shall be 0 when using two keys).
//------------------------------------------------------------------------------
void TDES_SetKeys(
    const unsigned int *pKey1,
    const unsigned int *pKey2,
    const unsigned int *pKey3)
{
    trace_LOG(trace_DEBUG, "-D- TDES_SetKeys()\n\r");
    SANITY_CHECK(pKey1);
    SANITY_CHECK((pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD))
                 || (!pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)));
    SANITY_CHECK((pKey3
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0))
                 ||
                 (!pKey3
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == AT91C_TDES_KEYMOD))
                 ||
                 (!pKey3
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)
                  && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0)));

    // Write key #1
    if (pKey1) {

        AT91C_BASE_TDES->TDES_KEY1WxR[0] = pKey1[0];
        AT91C_BASE_TDES->TDES_KEY1WxR[1] = pKey1[1];
    }

    // Write key #2
    if (pKey1) {

        AT91C_BASE_TDES->TDES_KEY2WxR[0] = pKey2[0];
        AT91C_BASE_TDES->TDES_KEY2WxR[1] = pKey2[1];
    }

    // Write key #2
    if (pKey1) {

        AT91C_BASE_TDES->TDES_KEY3WxR[0] = pKey3[0];
        AT91C_BASE_TDES->TDES_KEY3WxR[1] = pKey3[1];
    }
}
Beispiel #14
0
//------------------------------------------------------------------------------
/// Configures the triple-DES peripheral to cipher/decipher, use single-DES or
/// triple-DES, use two or three keys (when in triple-DES mode), start manually,
/// automatically or via the PDC and use the given operating mode (ECB, CBC,
/// CFB or OFB).
/// \param cipher  Encrypts if 1, decrypts if 0.
/// \param tdesmod  Single- or triple-DES mode.
/// \param keymod  Use two or three keys (must be 0 in single-DES mode).
/// \param smod  Start mode.
/// \param opmod  Encryption/decryption mode.
//------------------------------------------------------------------------------
void TDES_Configure(
    unsigned char cipher,
    unsigned int tdesmod,
    unsigned int keymod,
    unsigned int smod,
    unsigned int opmod)
{
    trace_LOG(trace_DEBUG, "-D- TDES_Configure()\n\r");
    SANITY_CHECK((cipher & 0xFFFFFFFE) == 0);
    SANITY_CHECK((tdesmod & 0xFFFFFFFD) == 0);
    SANITY_CHECK((keymod & 0xFFFFFFEF) == 0);
    SANITY_CHECK((smod & 0xFFFFFCFF) == 0);
    SANITY_CHECK((opmod & 0xFFFFCFFF) == 0);

    // Reset peripheral
    AT91C_BASE_TDES->TDES_CR = AT91C_TDES_SWRST;

    // Configure mode register
    AT91C_BASE_TDES->TDES_MR = cipher | tdesmod | keymod | smod | opmod;
}
//------------------------------------------------------------------------------
/// Starts a read operation on the TWI bus with the specified slave, and returns
/// immediately. Data must then be read using TWI_ReadByte() whenever a byte is
/// available (poll using TWI_ByteReceived()).
/// \param pTwi  Pointer to an AT91S_TWI instance.
/// \param address  Slave address on the bus.
/// \param iaddress  Optional internal address bytes.
/// \param isize  Number of internal address bytes.
//-----------------------------------------------------------------------------
void TWI_StartRead(
    AT91S_TWI *pTwi,
    unsigned char address,
    unsigned int iaddress,
    unsigned char isize)
{
    trace_LOG(trace_DEBUG, "-D- TWI_StartRead()\n\r");
    SANITY_CHECK(pTwi);
    SANITY_CHECK((address & 0x80) == 0);
    SANITY_CHECK((iaddress & 0xFF000000) == 0);
    SANITY_CHECK(isize < 4);

    // Set slave address and number of internal address bytes
    pTwi->TWI_MMR = (isize << 8) | AT91C_TWI_MREAD | (address << 16);

    // Set internal address bytes
    pTwi->TWI_IADR = iaddress;

    // Send START condition
    pTwi->TWI_CR = AT91C_TWI_START;
}
//-----------------------------------------------------------------------------
/// Starts a write operation on the TWI to access the selected slave, then
/// returns immediately. A byte of data must be provided to start the write;
/// other bytes are written next.
/// \param pTwi  Pointer to an AT91S_TWI instance.
/// \param address  Address of slave to acccess on the bus.
/// \param iaddress  Optional slave internal address.
/// \param isize  Number of internal address bytes.
/// \param byte  First byte to send.
//-----------------------------------------------------------------------------
void TWI_StartWrite(
    AT91S_TWI *pTwi,
    unsigned char address,
    unsigned int iaddress,
    unsigned char isize,
    unsigned char byte)
{
    trace_LOG(trace_DEBUG, "-D- TWI_StartWrite()\n\r");
    SANITY_CHECK(pTwi);
    SANITY_CHECK((address & 0x80) == 0);
    SANITY_CHECK((iaddress & 0xFF000000) == 0);
    SANITY_CHECK(isize < 4);

    // Set slave address and number of internal address bytes
    pTwi->TWI_MMR = (isize << 8) | (address << 16);

    // Set internal address bytes
    pTwi->TWI_IADR = iaddress;

    // Write first byte to send
    TWI_WriteByte(pTwi, byte);
}
Beispiel #17
0
//------------------------------------------------------------------------------
/// Reads and return a packet of data on the specified USART peripheral. This
/// function operates asynchronously, so it waits until some data has been
/// received.
/// \param usart  Pointer to an USART peripheral.
/// \param timeOut  Time out value (0 -> no timeout).
//------------------------------------------------------------------------------
unsigned short USART_Read(
    AT91S_USART *usart,
    volatile unsigned int timeOut)
{
    if (timeOut == 0) {

        while ((usart->US_CSR & AT91C_US_RXRDY) == 0);
    }
    else {

        while ((usart->US_CSR & AT91C_US_RXRDY) == 0) {

            if (timeOut == 0) {

                trace_LOG(trace_ERROR, "-E- USART_Read: Timed out.\n\r");
                return 0;
            }
            timeOut--;
        }
    }

    return usart->US_RHR;
}
//------------------------------------------------------------------------------
/// Enables the given interrupt source if it has been configured.
/// \param pPin  Interrupt source to enable.
//------------------------------------------------------------------------------
void PIO_EnableIt(const Pin *pPin)
{
    trace_LOG(trace_DEBUG, "-D- PIO_EnableIt()\n\r");

    SANITY_CHECK(pPin);

#ifndef NOASSERT
    unsigned int i = 0;
    unsigned char found = 0;
    while ((i < numSources) && !found) {

        if (pSources[i].pPin == pPin) {

            found = 1;
        }
        i++;
    }
    ASSERT(found, "-F- PIO_EnableIt: Interrupt source has not been configured\n\r");
#endif

    pPin->pio->PIO_ISR;
    pPin->pio->PIO_IER = pPin->mask;
}
Beispiel #19
0
//-----------------------------------------------------------------------------
/// Wait PHY operation complete.
/// Return 1 if the operation completed successfully.
/// May be need to re-implemented to reduce CPU load.
/// \param retry: the retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
static unsigned char EMAC_WaitPhy( unsigned int retry )
{
    unsigned int retry_count = 0;

    while((AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE) == 0) {

        // Dead LOOP!
        if (retry == 0) {

            continue;
        }

        // Timeout check
        retry_count++;
        if(retry_count >= retry) {

            trace_LOG(trace_ERROR, "E: Wait PHY time out\n\r");
            return 0;
        }
    }

    return 1;
}
Beispiel #20
0
//-----------------------------------------------------------------------------
/// Set MDC clock according to current board clock. Per 802.3, MDC should be
/// less then 2.5MHz.
/// Return 1 if successfully, 0 if MDC clock not found.
//-----------------------------------------------------------------------------
unsigned char EMAC_SetMdcClock( unsigned int mck )
{
    int clock_dividor;

    if (mck <= 20000000) {
        clock_dividor = AT91C_EMAC_CLK_HCLK_8;          /// MDC clock = MCK/8
    }
    else if (mck <= 40000000) {
        clock_dividor = AT91C_EMAC_CLK_HCLK_16;         /// MDC clock = MCK/16
    }
    else if (mck <= 80000000) {
        clock_dividor = AT91C_EMAC_CLK_HCLK_32;         /// MDC clock = MCK/32
    }
    else if (mck <= 160000000) {
        clock_dividor = AT91C_EMAC_CLK_HCLK_64;         /// MDC clock = MCK/64
    }
    else {
        trace_LOG(trace_ERROR, "E: No valid MDC clock.\n\r");
        return 0;
    }
    AT91C_BASE_EMAC->EMAC_NCFGR = (AT91C_BASE_EMAC->EMAC_NCFGR & (~AT91C_EMAC_CLK))
                                 | clock_dividor;
    return 1;
}
Beispiel #21
0
//------------------------------------------------------------------------------
/// Sends one packet of data through the specified USART peripheral. This
/// function operates synchronously, so it only returns when the data has been
/// actually sent.
/// \param usart  Pointer to an USART peripheral.
/// \param data  Data to send including 9nth bit and sync field if necessary (in
///              the same format as the US_THR register in the datasheet).
/// \param timeOut  Time out value (0 = no timeout).
//------------------------------------------------------------------------------
void USART_Write(
    AT91S_USART *usart,
    unsigned short data,
    volatile unsigned int timeOut)
{
    if (timeOut == 0) {

        while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0);
    }
    else {

        while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0) {

            if (timeOut == 0) {

                trace_LOG(trace_ERROR, "-E- USART_Write: Timed out.\n\r");
                return;
            }
            timeOut--;
        }
    }

    usart->US_THR = data;
}
Beispiel #22
0
//------------------------------------------------------------------------------
/// Handles the given request if it is standard, otherwise STALLs it.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param pRequest  Pointer to a USBGenericRequest instance.
//------------------------------------------------------------------------------
void USBDDriver_RequestHandler(
    USBDDriver *pDriver,
    const USBGenericRequest *pRequest)
{
    unsigned char cfgnum;
    unsigned char infnum;
    unsigned char eptnum;
    unsigned char setting;
    unsigned char type;
    unsigned char index;
    unsigned int length;
    unsigned int address;

    trace_LOG(trace_INFO, "Std ");

    // Check request code
    switch (USBGenericRequest_GetRequest(pRequest)) {

        case USBGenericRequest_GETDESCRIPTOR:
            trace_LOG(trace_INFO, "gDesc ");

            // Send the requested descriptor
            type = USBGetDescriptorRequest_GetDescriptorType(pRequest);
            index = USBGetDescriptorRequest_GetDescriptorIndex(pRequest);
            length = USBGenericRequest_GetLength(pRequest);
            GetDescriptor(pDriver, type, index, length);
            break;

        case USBGenericRequest_SETADDRESS:
            trace_LOG(trace_INFO, "sAddr ");

            // Sends a zero-length packet and then set the device address
            address = USBSetAddressRequest_GetAddress(pRequest);

            if( USBD_IsHighSpeed() ) {

                USBD_SetAddress( address );
            }
            else {
                USBD_Write(0, 0, 0, (TransferCallback) USBD_SetAddress, (void *) address);
            }
            break;

        case USBGenericRequest_SETCONFIGURATION:
            trace_LOG(trace_INFO, "sCfg ");

            // Set the requested configuration
            cfgnum = USBSetConfigurationRequest_GetConfiguration(pRequest);
            SetConfiguration(pDriver, cfgnum);
            break;

        case USBGenericRequest_GETCONFIGURATION:
            trace_LOG(trace_INFO, "gCfg ");

            // Send the current configuration number
            GetConfiguration(pDriver);
            break;

        case USBGenericRequest_GETSTATUS:
            trace_LOG(trace_INFO, "gSta ");
    
            // Check who is the recipient
            switch (USBGenericRequest_GetRecipient(pRequest)) {
    
                case USBGenericRequest_DEVICE:
                    trace_LOG(trace_INFO, "Dev ");
    
                    // Send the device status
                    GetDeviceStatus(pDriver);
                    break;
    
                case USBGenericRequest_ENDPOINT:
                    trace_LOG(trace_INFO, "Ept ");
    
                    // Send the endpoint status
                    eptnum = USBGenericRequest_GetEndpointNumber(pRequest);
                    GetEndpointStatus(eptnum);
                    break;
    
                default:
                    trace_LOG(trace_WARNING,
                              "W: USBDDriver_RequestHandler: Unknown recipient (%d)\n\r",
                              USBGenericRequest_GetRecipient(pRequest));
                    USBD_Stall(0);
            }
            break;

        case USBGenericRequest_CLEARFEATURE:
            trace_LOG(trace_INFO, "cFeat ");

            // Check which is the requested feature
            switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

                case USBFeatureRequest_ENDPOINTHALT:
                    trace_LOG(trace_INFO, "Hlt ");

                    // Unhalt endpoint and send a zero-length packet
                    USBD_Unhalt(USBGenericRequest_GetEndpointNumber(pRequest));
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                    trace_LOG(trace_INFO, "RmWU ");

                    // Disable remote wake-up and send a zero-length packet
                    pDriver->isRemoteWakeUpEnabled = 0;
                    USBD_Write(0, 0, 0, 0, 0);
                    break;

                default:
                    trace_LOG(trace_WARNING,
                              "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                              USBFeatureRequest_GetFeatureSelector(pRequest));
                    USBD_Stall(0);
            }
            break;

    case USBGenericRequest_SETFEATURE:
        trace_LOG(trace_INFO, "sFeat ");

        // Check which is the selected feature
        switch (USBFeatureRequest_GetFeatureSelector(pRequest)) {

            case USBFeatureRequest_DEVICEREMOTEWAKEUP:
                trace_LOG(trace_INFO, "RmWU ");

                // Enable remote wake-up and send a ZLP
                pDriver->isRemoteWakeUpEnabled = 1;
                USBD_Write(0, 0, 0, 0, 0);
                break;

            case USBFeatureRequest_ENDPOINTHALT:
                trace_LOG(trace_INFO, "Ept ");

                // Halt endpoint
                USBD_Halt(USBGenericRequest_GetEndpointNumber(pRequest));
                USBD_Write(0, 0, 0, 0, 0);
                break;

#if defined(BOARD_USB_UDPHS)

            case USBFeatureRequest_TESTMODE:
                // 7.1.20 Test Mode Support
                if ((USBGenericRequest_GetType(pRequest) == USBGenericRequest_DEVICE)
                    && ((USBGenericRequest_GetIndex(pRequest) & 0x000F) == 0)) {

                    // Handle test request
                    USBDDriver_Test(USBFeatureRequest_GetTestSelector(pRequest));
                }
                else {

                    USBD_Stall(0);
                }
                break;
#endif

            default:
                trace_LOG(trace_WARNING,
                          "USBDDriver_RequestHandler: Unknown feature selector (%d)\n\r",
                          USBFeatureRequest_GetFeatureSelector(pRequest));
                USBD_Stall(0);
        }
        break;

    case USBGenericRequest_SETINTERFACE:
        trace_LOG(trace_INFO, "sInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        setting = USBInterfaceRequest_GetAlternateSetting(pRequest);
        SetInterface(pDriver, infnum, setting);
        break;

    case USBGenericRequest_GETINTERFACE:
        trace_LOG(trace_INFO, "gInterface ");

        infnum = USBInterfaceRequest_GetInterface(pRequest);
        GetInterface(pDriver, infnum);
        break;

    default:
        trace_LOG(trace_WARNING,
                  "USBDDriver_RequestHandler: Unknown request code (%d)\n\r",
                  USBGenericRequest_GetRequest(pRequest));
        USBD_Stall(0);
    }
}
//------------------------------------------------------------------------------
/// Initializes the PIO interrupt management logic.
/// \param priority  PIO controller interrupts priority.
//------------------------------------------------------------------------------
void PIO_InitializeInterrupts(unsigned int priority)
{
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize()\n\r");

    SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0);

    // Reset sources
    numSources = 0;

#ifdef AT91C_ID_PIOA
    // Configure PIO interrupt sources
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOA\n\r");
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
    AT91C_BASE_PIOA->PIO_ISR;
    AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
    AIC_ConfigureIT(AT91C_ID_PIOA, priority, InterruptHandler);
    AIC_EnableIT(AT91C_ID_PIOA);
#endif

#ifdef AT91C_ID_PIOB
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOB\n\r");
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB;
    AT91C_BASE_PIOB->PIO_ISR;
    AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF;
    AIC_ConfigureIT(AT91C_ID_PIOB, priority, InterruptHandler);
    AIC_EnableIT(AT91C_ID_PIOB);
#endif

#ifdef AT91C_ID_PIOC
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOC;
    AT91C_BASE_PIOC->PIO_ISR;
    AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
    AIC_ConfigureIT(AT91C_ID_PIOC, priority, InterruptHandler);
    AIC_EnableIT(AT91C_ID_PIOC);
#endif

#ifdef AT91C_ID_PIOD
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOD\n\r");
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOD;
    AT91C_BASE_PIOC->PIO_ISR;
    AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
    AIC_ConfigureIT(AT91C_ID_PIOD, priority, InterruptHandler);
    AIC_EnableIT(AT91C_ID_PIOD);
#endif

#ifdef AT91C_ID_PIOE
    trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOE\n\r");
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOE;
    AT91C_BASE_PIOC->PIO_ISR;
    AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
    AIC_ConfigureIT(AT91C_ID_PIOE, priority, InterruptHandler);
    AIC_EnableIT(AT91C_ID_PIOE);
#endif

#if defined(AT91C_ID_PIOABCD)
    // Treat PIOABCD interrupts
    #if !defined(AT91C_ID_PIOA) \
     && !defined(AT91C_ID_PIOB) \
     && !defined(AT91C_ID_PIOC) \
     && !defined(AT91C_ID_PIOD)

        trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCD\n\r");
        AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCD;
        AT91C_BASE_PIOA->PIO_ISR;
        AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
        AIC_ConfigureIT(AT91C_ID_PIOABCD, priority, InterruptHandler);
        AIC_EnableIT(AT91C_ID_PIOABCD);
    #endif
#endif

#if defined(AT91C_ID_PIOABCDE)
    // Treat PIOABCDE interrupts
    #if !defined(AT91C_ID_PIOA) \
     && !defined(AT91C_ID_PIOB) \
     && !defined(AT91C_ID_PIOC) \
     && !defined(AT91C_ID_PIOD) \
     && !defined(AT91C_ID_PIOE)

        trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCDE\n\r");
        AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCDE;
        AT91C_BASE_PIOA->PIO_ISR;
        AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
        AIC_ConfigureIT(AT91C_ID_PIOABCDE, priority, InterruptHandler);
        AIC_EnableIT(AT91C_ID_PIOABCDE);
    #endif
#endif

#if defined(AT91C_ID_PIOCDE)
    // Treat PIOCDE interrupts
    #if !defined(AT91C_ID_PIOC) \
     && !defined(AT91C_ID_PIOD) \
     && !defined(AT91C_ID_PIOE)

        trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");
        AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOCDE;
        AT91C_BASE_PIOC->PIO_ISR;
        AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
        AIC_ConfigureIT(AT91C_ID_PIOCDE, priority, InterruptHandler);
        AIC_EnableIT(AT91C_ID_PIOCDE);
    #endif
#endif
}
Beispiel #24
0
//------------------------------------------------------------------------------
/// Returns the current status register value of the TDES peripheral.
//------------------------------------------------------------------------------
unsigned int TDES_GetStatus(void)
{
    trace_LOG(trace_DEBUG, "-D- TDES_GetStatus()\n\r");

    return AT91C_BASE_TDES->TDES_ISR;
}
Beispiel #25
0
//-----------------------------------------------------------------------------
/// Receive a packet with EMAC
/// If not enough buffer for the packet, the remaining data is lost but right
/// frame length is returned.
/// \param pFrame           Buffer to store the frame
/// \param frameSize        Size of the frame
/// \param pRcvSize         Received size
/// \return                 OK, no data, or frame too small
//-----------------------------------------------------------------------------
unsigned char EMAC_Poll(unsigned char *pFrame,
                        unsigned int frameSize,
                        unsigned int *pRcvSize)
{
    unsigned short bufferLength;
    unsigned int   tmpFrameSize=0;
    unsigned char  *pTmpFrame=0;
    unsigned int   tmpIdx = rxTd.idx;
    volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;

    ASSERT(pFrame, "F: EMAC_Poll\n\r");

    char isFrame = 0;
    // Set the default return value
    *pRcvSize = 0;

    // Process received RxTd
    while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {

        // A start of frame has been received, discard previous fragments
        if ((pRxTd->status & EMAC_RX_SOF_BIT) == EMAC_RX_SOF_BIT) {
            // Skip previous fragment
            while (tmpIdx != rxTd.idx) {
                pRxTd = rxTd.td + rxTd.idx;
                pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
                CIRC_INC(rxTd.idx, RX_BUFFERS);
            }
            // Reset the temporary frame pointer
            pTmpFrame = pFrame;
            tmpFrameSize = 0;
            // Start to gather buffers in a frame
            isFrame = 1;
        }

        // Increment the pointer
        CIRC_INC(tmpIdx, RX_BUFFERS);

        // Copy data in the frame buffer
        if (isFrame) {
            if (tmpIdx == rxTd.idx) {
                trace_LOG(trace_INFO,
                    "I: no EOF (Invalid of buffers too small)\n\r");

                do {

                    pRxTd = rxTd.td + rxTd.idx;
                    pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
                    CIRC_INC(rxTd.idx, RX_BUFFERS);
                } while(tmpIdx != rxTd.idx);
                return EMAC_RX_NO_DATA;
            }
            // Copy the buffer into the application frame
            bufferLength = EMAC_RX_UNITSIZE;
            if ((tmpFrameSize + bufferLength) > frameSize) {
                bufferLength = frameSize - tmpFrameSize;
            }

            memcpy(pTmpFrame, (void*)(pRxTd->addr & EMAC_ADDRESS_MASK), bufferLength);
            pTmpFrame += bufferLength;
            tmpFrameSize += bufferLength;

            // An end of frame has been received, return the data
            if ((pRxTd->status & EMAC_RX_EOF_BIT) == EMAC_RX_EOF_BIT) {
                // Frame size from the EMAC
                *pRcvSize = (pRxTd->status & EMAC_LENGTH_FRAME);

                // Application frame buffer is too small all data have not been copied
                if (tmpFrameSize < *pRcvSize) {
                    printf("size req %u size allocated %u\n\r", *pRcvSize, frameSize);

                    return EMAC_RX_FRAME_SIZE_TOO_SMALL;
                }

                trace_LOG(trace_INFO, "packet %d-%u (%u)\n\r", rxTd.idx, tmpIdx, *pRcvSize);
                // All data have been copied in the application frame buffer => release TD
                while (rxTd.idx != tmpIdx) {
                    pRxTd = rxTd.td + rxTd.idx;
                    pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
                    CIRC_INC(rxTd.idx, RX_BUFFERS);
                }
                EmacStatistics.rx_packets++;
                return EMAC_RX_OK;
            }
        }

        // SOF has not been detected, skip the fragment
        else {
           pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
           rxTd.idx = tmpIdx;
        }

        // Process the next buffer
        pRxTd = rxTd.td + tmpIdx;
    }

    //trace_LOG(trace_DEBUG, "E");
    return EMAC_RX_NO_DATA;
}
Beispiel #26
0
//-----------------------------------------------------------------------------
/// Send a packet with EMAC.
/// If the packet size is larger than transfer buffer size error returned.
/// \param buffer   The buffer to be send
/// \param size     The size of buffer to be send
/// \param fEMAC_TxCallback Threshold Wakeup callback
/// \param fWakeUpCb   TX Wakeup
/// \return         OK, Busy or invalid packet
//-----------------------------------------------------------------------------
unsigned char EMAC_Send(void *pBuffer,
                        unsigned int size,
                        EMAC_TxCallback fEMAC_TxCallback)
{
    volatile EmacTxTDescriptor *pTxTd;
    volatile EMAC_TxCallback   *pTxCb;

    //trace_LOG(trace_DEBUG, "EMAC_Send\n\r");

    // Check parameter
    if (size > EMAC_TX_UNITSIZE) {

        trace_LOG(trace_ERROR, "-E- EMAC driver does not split send packets.");
        trace_LOG(trace_ERROR, " It can send %d bytes max in one packet (%u bytes requested)\n\r",
            EMAC_TX_UNITSIZE, size);
        return EMAC_TX_INVALID_PACKET;
    }

    // If no free TxTd, buffer can't be sent, schedule the wakeup callback
    if( CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) == 0) {
        return EMAC_TX_BUFFER_BUSY;

    }

    // Pointers to the current TxTd
    pTxTd = txTd.td + txTd.head;
    pTxCb = txTd.txCb + txTd.head;

    // Sanity check
    ASSERT((pTxTd->status & EMAC_TX_USED_BIT) != 0,
        "-F- Buffer is still under EMAC control\n\r");

    // Setup/Copy data to transmition buffer
    if (pBuffer && size) {
        // Driver manage the ring buffer
        memcpy((void *)pTxTd->addr, pBuffer, size);
    }

    // Tx Callback
    *pTxCb = fEMAC_TxCallback;

    // Update TD status
    // The buffer size defined is length of ethernet frame
    // so it's always the last buffer of the frame.
    if (txTd.head == TX_BUFFERS-1) {
        pTxTd->status =
            (size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT | EMAC_TX_WRAP_BIT;
    }
    else {
        pTxTd->status = (size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT;
    }

    CIRC_INC(txTd.head, TX_BUFFERS)

    // Tx packets count
    EmacStatistics.tx_packets++;

    // Now start to transmit if it is not already done
    AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;

    return EMAC_TX_OK;
}
Beispiel #27
0
//-----------------------------------------------------------------------------
/// Initialize the EMAC with the emac controller address
/// \param id     HW ID for power management
/// \param pTxWakeUpfct Thresold TX Wakeup Callback
/// \param pRxfct       RX Wakeup Callback
/// \param pMacAddress  Mac Address
/// \param enableCAF    enable AT91C_EMAC_CAF if needed by application
/// \param enableNBC    AT91C_EMAC_NBC if needed by application
//-----------------------------------------------------------------------------
void EMAC_Init( unsigned char id, const unsigned char *pMacAddress,
                unsigned char enableCAF, unsigned char enableNBC )
{
    int Index;
    unsigned int Address;

    // Check parameters
    ASSERT(RX_BUFFERS * EMAC_RX_UNITSIZE > EMAC_FRAME_LENTGH_MAX,
           "E: RX buffers too small\n\r");

    trace_LOG(trace_DEBUG, "EMAC_Init\n\r");

    // Power ON
    AT91C_BASE_PMC->PMC_PCER = 1 << id;

    // Disable TX & RX and more
    AT91C_BASE_EMAC->EMAC_NCR = 0;

    // disable
    AT91C_BASE_EMAC->EMAC_IDR = ~0;

    rxTd.idx = 0;
    CIRC_CLEAR(&txTd);

    // Setup the RX descriptors.
    for(Index = 0; Index < RX_BUFFERS; Index++) {

        Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
        // Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
        rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
        rxTd.td[Index].status = 0;
    }
    rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;

    // Setup the TX descriptors.
    for(Index = 0; Index < TX_BUFFERS; Index++) {

        Address = (unsigned int)(&(pTxBuffer[Index * EMAC_TX_UNITSIZE]));
        txTd.td[Index].addr = Address;
        txTd.td[Index].status = EMAC_TX_USED_BIT;
    }
    txTd.td[TX_BUFFERS - 1].status = EMAC_TX_USED_BIT | EMAC_TX_WRAP_BIT;

    // Set the MAC address
    if( pMacAddress != (unsigned char *)0 ) {
        AT91C_BASE_EMAC->EMAC_SA1L = ( ((unsigned int)pMacAddress[3] << 24)
                                     | ((unsigned int)pMacAddress[2] << 16)
                                     | ((unsigned int)pMacAddress[1] << 8 )
                                     |                pMacAddress[0] );

        AT91C_BASE_EMAC->EMAC_SA1H = ( ((unsigned int)pMacAddress[5] << 8 )
                                     |                pMacAddress[4] );
    }
    // Now setup the descriptors
    // Receive Buffer Queue Pointer Register
    AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
    // Transmit Buffer Queue Pointer Register
    AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int) (txTd.td);

    AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_CLRSTAT;

    // Clear all status bits in the receive status register.
    AT91C_BASE_EMAC->EMAC_RSR = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);

    // Clear all status bits in the transmit status register
    AT91C_BASE_EMAC->EMAC_TSR = ( AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES
                                | AT91C_EMAC_BEX | AT91C_EMAC_COMP
                                | AT91C_EMAC_UND );

    // Clear interrupts
    AT91C_BASE_EMAC->EMAC_ISR;

    // Enable the copy of data into the buffers
    // ignore broadcasts, and don't copy FCS.
    AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_DRFCS | AT91C_EMAC_PAE);

    if( enableCAF == EMAC_CAF_ENABLE ) {
        AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF;
    }
    if( enableNBC == EMAC_NBC_ENABLE ) {
        AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_NBC;
    }

    // Enable Rx and Tx, plus the stats register.
    AT91C_BASE_EMAC->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);

    // Setup the interrupts for TX (and errors)
    AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RXUBR
                              | AT91C_EMAC_TUNDR
                              | AT91C_EMAC_RLEX
                              | AT91C_EMAC_TXERR
                              | AT91C_EMAC_TCOMP
                              | AT91C_EMAC_ROVR
                              | AT91C_EMAC_HRESP;

}
Beispiel #28
0
//------------------------------------------------------------------------------
// Performs the selected test on the USB device (high-speed only).
// \param test  Test selector value.
//------------------------------------------------------------------------------
static void USBDDriver_Test(unsigned char test)
{
    trace_LOG(trace_DEBUG, "UDPHS_Test\n\r");

    // the lower byte of wIndex must be zero
    // the most significant byte of wIndex is used to specify the specific test mode
    switch (test) {
        case USBFeatureRequest_TESTPACKET:
            //Test mode Test_Packet: 
            //Upon command, a port must repetitively transmit the following test packet until
            //the exit action is taken. This enables the testing of rise and fall times, eye 
            //patterns, jitter, and any other dynamic waveform specifications.
            //The test packet is made up by concatenating the following strings. 
            //(Note: For J/K NRZI data, and for NRZ data, the bit on the left is the first one 
            //transmitted. “S” indicates that a bit stuff occurs, which inserts an “extra” NRZI data bit. 
            //“* N” is used to indicate N occurrences of a string of bits or symbols.)
            //A port in Test_Packet mode must send this packet repetitively. The inter-packet timing 
            //must be no less than the minimum allowable inter-packet gap as defined in Section 7.1.18 and 
            //no greater than 125 us.
            // Send ZLP
            USBD_Test(USBFeatureRequest_TESTSENDZLP);
            // Tst PACKET
            USBD_Test(USBFeatureRequest_TESTPACKET);
            while (1);
            break;

        case USBFeatureRequest_TESTJ:
            //Test mode Test_J:
            //Upon command, a port’s transceiver must enter the high-speed J state and remain in that
            //state until the exit action is taken. This enables the testing of the high output drive
            //level on the D+ line.
            // Send ZLP
            USBD_Test(USBFeatureRequest_TESTSENDZLP);
            // Tst J
            USBD_Test(USBFeatureRequest_TESTJ);
            while (1);
            break;

        case USBFeatureRequest_TESTK:
            //Test mode Test_K:
            //Upon command, a port’s transceiver must enter the high-speed K state and remain in
            //that state until the exit action is taken. This enables the testing of the high output drive
            //level on the D- line.
            // Send a ZLP
            USBD_Test(USBFeatureRequest_TESTSENDZLP);
            USBD_Test(USBFeatureRequest_TESTK);
            while (1);
            break;

        case USBFeatureRequest_TESTSE0NAK:
            //Test mode Test_SE0_NAK:
            //Upon command, a port’s transceiver must enter the high-speed receive mode
            //and remain in that mode until the exit action is taken. This enables the testing
            //of output impedance, low level output voltage, and loading characteristics.
            //In addition, while in this mode, upstream facing ports (and only upstream facing ports)
            //must respond to any IN token packet with a NAK handshake (only if the packet CRC is
            //determined to be correct) within the normal allowed device response time. This enables testing of
            //the device squelch level circuitry and, additionally, provides a general purpose stimulus/response
            //test for basic functional testing.
            USBD_Test(USBFeatureRequest_TESTSE0NAK);
            // Send a ZLP
            USBD_Test(USBFeatureRequest_TESTSENDZLP);
            while (1);
            break;

        default:
            USBD_Stall( 0 );
            break;

    }
    // The exit action is to power cycle the device.
    // The device must be disconnected from the host
}
Beispiel #29
0
//------------------------------------------------------------------------------
/// Processes pending events on the given MCI driver.
/// \param pMci  Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
void MCI_Handler(Mci *pMci)
{
    AT91S_MCI *pMciHw = pMci->pMciHw;
    MciCmd *pCommand = pMci->pCommand;
    unsigned int status;
    unsigned char i;
#if defined(at91rm9200)
    unsigned int mciCr, mciSdcr, mciMr, mciDtor;
#endif

    SANITY_CHECK(pMci);
    SANITY_CHECK(pMciHw);
    SANITY_CHECK(pCommand);

    // Read the status register
    status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);
    // trace_LOG(trace_DEBUG, "status %x\n\r", status);

    // Check if an error has occured
    if ((status & STATUS_ERRORS) != 0) {

        // Check error code
        if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {

            pCommand->status = MCI_STATUS_NORESPONSE;
        }
        // if the command is SEND_OP_COND the CRC error flag is always present
        // (cf : R3 response)
        else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
                 || ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)
                     && (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {

            pCommand->status = MCI_STATUS_ERROR;
        }
    }

    // Check if a transfer has been completed
    if (((status & AT91C_MCI_CMDRDY) != 0)
            || ((status & AT91C_MCI_ENDRX) != 0)
            || ((status & AT91C_MCI_RXBUFF) != 0)
            || ((status & AT91C_MCI_ENDTX) != 0)
            || ((status & AT91C_MCI_BLKE) != 0)
            || ((status & AT91C_MCI_RTOE) != 0)) {

        if (((status & AT91C_MCI_ENDRX) != 0)
                || ((status & AT91C_MCI_RXBUFF) != 0)
                || ((status & AT91C_MCI_ENDTX) != 0)) {

            MCI_Enable(pMci, DISABLE);
        }

        /// On AT91RM9200-EK, if stop transmission, software reset MCI.
#if defined(at91rm9200)
        if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {
            mciMr = READ_MCI(pMciHw, MCI_MR);
            mciSdcr = READ_MCI(pMciHw, MCI_SDCR);
            mciDtor = READ_MCI(pMciHw, MCI_DTOR);
            WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
            // trace_LOG(trace_DEBUG, "reset MCI\n\r");

            WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
            WRITE_MCI(pMciHw, MCI_MR, mciMr);
            WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);
            WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);
        }
#endif

        // If no error occured, the transfer is successful
        if (pCommand->status == MCI_STATUS_PENDING) {
            pCommand->status = 0;
        }
#if 0
        if ((status & AT91C_MCI_CMDRDY) != 0)
            trace_LOG(trace_DEBUG, ".");
        if ((status & AT91C_MCI_ENDRX) != 0)
            trace_LOG(trace_DEBUG, "<");
        if ((status & AT91C_MCI_ENDTX) != 0)
            trace_LOG(trace_DEBUG, "-");
        if ((status & AT91C_MCI_BLKE) != 0)
            trace_LOG(trace_DEBUG, ">");
        trace_LOG(trace_DEBUG, "\n\r");
#endif
        // Store the card response in the provided buffer
        if (pCommand->pResp) {

            for (i=0; i < pCommand->resSize; i++) {

                pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
            }
        }

        // Disable interrupts
        WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));

        // Release the semaphore
        pMci->semaphore++;

        // Invoke the callback associated with the current command (if any)
        if (pCommand->callback) {
            (pCommand->callback)(pCommand->status, pCommand);
        }
    }
}
Beispiel #30
0
//------------------------------------------------------------------------------
/// Sends the requested USB descriptor to the host if available, or STALLs  the
/// request.
/// \param pDriver  Pointer to a USBDDriver instance.
/// \param type  Type of the requested descriptor
/// \param index  Index of the requested descriptor.
/// \param length  Maximum number of bytes to return.
//------------------------------------------------------------------------------
static void GetDescriptor(
    const USBDDriver *pDriver,
    unsigned char type,
    unsigned char index,
    unsigned int length)
{
    const USBDeviceDescriptor *pDevice;
    const USBConfigurationDescriptor *pConfiguration;
    const USBDeviceQualifierDescriptor *pQualifier;
    const USBConfigurationDescriptor *pOtherSpeed;
    const USBGenericDescriptor **pStrings =
        (const USBGenericDescriptor **) pDriver->pDescriptors->pStrings;
    unsigned char numStrings = pDriver->pDescriptors->numStrings;
    const USBGenericDescriptor *pString;

    // Use different set of descriptors depending on device speed
    if (USBD_IsHighSpeed()) {

        trace_LOG(trace_DEBUG, "HS ");
        pDevice = pDriver->pDescriptors->pHsDevice;
        pConfiguration = pDriver->pDescriptors->pHsConfiguration;
        pQualifier = pDriver->pDescriptors->pHsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pHsOtherSpeed;
    }
    else {

        trace_LOG(trace_DEBUG, "FS ");
        pDevice = pDriver->pDescriptors->pFsDevice;
        pConfiguration = pDriver->pDescriptors->pFsConfiguration;
        pQualifier = pDriver->pDescriptors->pFsQualifier;
        pOtherSpeed = pDriver->pDescriptors->pFsOtherSpeed;
    }

    // Check the descriptor type
    switch (type) {
        
        case USBGenericDescriptor_DEVICE:
            trace_LOG(trace_INFO, "Dev ");

            // Adjust length and send descriptor
            if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice)) {

                length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pDevice);
            }
            USBD_Write(0, pDevice, length, 0, 0);
            break;

        case USBGenericDescriptor_CONFIGURATION:
            trace_LOG(trace_INFO, "Cfg ");

            // Adjust length and send descriptor
            if (length > USBConfigurationDescriptor_GetTotalLength(pConfiguration)) {

                length = USBConfigurationDescriptor_GetTotalLength(pConfiguration);
            }
            USBD_Write(0, pConfiguration, length, 0, 0);
            break;

        case USBGenericDescriptor_DEVICEQUALIFIER:
            trace_LOG(trace_INFO, "Qua ");

            // Check if descriptor exists
            if (!pQualifier) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier)) {

                    length = USBGenericDescriptor_GetLength((USBGenericDescriptor *) pQualifier);
                }
                USBD_Write(0, pQualifier, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_OTHERSPEEDCONFIGURATION:
            trace_LOG(trace_INFO, "OSC ");

            // Check if descriptor exists
            if (!pOtherSpeed) {

                USBD_Stall(0);
            }
            else {

                // Adjust length and send descriptor
                if (length > USBConfigurationDescriptor_GetTotalLength(pOtherSpeed)) {

                    length = USBConfigurationDescriptor_GetTotalLength(pOtherSpeed);
                }
                USBD_Write(0, pOtherSpeed, length, 0, 0);
            }
            break;

        case USBGenericDescriptor_STRING:
            trace_LOG(trace_INFO, "Str%d ", index);

            // Check if descriptor exists
            if (index > numStrings) {

                USBD_Stall(0);
            }
            else {

                pString = pStrings[index];

                // Adjust length and send descriptor
                if (length > USBGenericDescriptor_GetLength(pString)) {

                    length = USBGenericDescriptor_GetLength(pString);
                }
                USBD_Write(0, pString, length, 0, 0);
            }
            break;

        default:
            trace_LOG(trace_WARNING,
                      "USBDDriver_GetDescriptor: Unknown descriptor type (%d)\n\r",
                      type);
            USBD_Stall(0);
    }
}