Exemple #1
0
AJ_EXPORT AJ_Status AJ_WSL_WriteBufListToMBox(uint8_t box, uint8_t endpoint, uint16_t len, AJ_BufList* list)
{
    AJ_Status status = AJ_ERR_SPI_WRITE;
    uint16_t spaceAvailable = 0;
    uint16_t bytesRemaining;
    uint16_t cause = 0;

    AJ_ASSERT(0 == box);
//    AJ_InfoPrintf(("=HTC Credits 0:%x, 1:%x, 2:%x\n", AJ_WSL_HTC_Global.endpoints[0].txCredits, AJ_WSL_HTC_Global.endpoints[1].txCredits, AJ_WSL_HTC_Global.endpoints[2].txCredits));
    AJ_Time credit_timer;
    AJ_InitTimer(&credit_timer);
    while (AJ_WSL_HTC_Global.endpoints[endpoint].txCredits < 1) {
        // do nothing and wait until there are credits
        if (AJ_GetElapsedTime(&credit_timer, TRUE) > 1500) {
            AJ_WSL_HTC_Global.endpoints[endpoint].txCredits++;
            break;
        }
        AJ_YieldCurrentTask();
    }

    // don't let the other tasks interrupt our SPI access
    AJ_EnterCriticalRegion();


    AJ_Time space_timer;
    AJ_InitTimer(&space_timer);
    // read space available in mbox from register
    do {
        if (AJ_GetElapsedTime(&space_timer, TRUE) > 1500) {
            spaceAvailable = 0xc5b;
            AJ_WSL_SPI_RegisterWrite(AJ_WSL_SPI_REG_SPI_CONFIG, 1 << 15);
            break;
        }
        status = AJ_WSL_GetWriteBufferSpaceAvailable(&spaceAvailable);
    } while (spaceAvailable == 0);

    AJ_ASSERT((status == AJ_OK) && (spaceAvailable >= len));
    if ((status == AJ_OK) && (spaceAvailable >= len)) {
        uint16_t targetAddress;


        // write size to be transferred
        status = AJ_WSL_SetDMABufferSize(len);
        AJ_ASSERT(status == AJ_OK);

        // write the target address (where we want to send data)
        // the write should end up at the end of the MBox alias
        // example 0xFFF - len
        targetAddress = AJ_WSL_SPI_MBOX_0_EOM_ALIAS - len;
        status = AJ_WSL_SPI_DMAWriteStart(targetAddress);
        AJ_ASSERT(status == AJ_OK);

        bytesRemaining = len;

        // Take the AJ_BufList to write out and write it out to the SPI interface via DMA
        AJ_WSL_BufListIterate_DMA(list);

        // clear the packet available interrupt
        cause = 0x1f;
        status = AJ_WSL_SPI_RegisterWrite(AJ_WSL_SPI_REG_INTR_ENABLE, cause);
        AJ_ASSERT(status == AJ_OK);


        AJ_WSL_HTC_Global.endpoints[endpoint].txCredits -= 1;


    } else {
        status = AJ_ERR_SPI_NO_SPACE;
    }
    AJ_LeaveCriticalRegion();
    return status;
}
Exemple #2
0
void AJ_WSL_MBoxListenAndProcessTask(void* parameters)
{
    g_b_spi_interrupt_data_ready = FALSE;
    AJ_WSL_SPI_InitializeSPIController();

    set_SPI_registers();
    write_BOOT_PARAM();

    g_b_spi_interrupt_data_ready = FALSE;

    // loop and process all of the responses
    while (1) {
        AJ_Status status;

        AJ_WSL_HTC_ProcessInterruptCause();

        uint8_t i;
        for (i = 0; i < AJ_WSL_SOCKET_MAX; i++) {
            do {
                wsl_work_item* item = NULL;

                // peek at the queue, then make sure we have enough credits
                // if we have enough, pull and send the workitem to the MBOX
                // otherwise, move to the next socket and then eventually out of this loop.
                // Credits would be available again once AJ_WSL_HTC_ProcessInterruptCause has
                // read any credit-adjustment trailers
                status = AJ_QueuePeek(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &item);
                if ((status != AJ_OK) || (AJ_WSL_HTC_Global.endpoints[item->endpoint].txCredits < 1)) {
                    break;
                }

                // pull a work item off of a socket queue and send it
                AJ_QueuePull(AJ_WSL_SOCKET_CONTEXT[i].workTxQueue, &item, 0);
                if (!item) {
                    break;
                } else {
                    //AJ_AlwaysPrintf(("AJ_WSL_MBoxListenAndProcessTask: %x\n", item->itemType));
                    AJ_WSL_WriteBufListToMBox(0, item->endpoint, AJ_BufListLengthOnWire(item->list), item->list);

                    /*
                     * if this item is sending data, create a workitem indicating completion
                     * this special check is needed because there is no socket send command in WMI,
                     * otherwise we could handle it in AJ_WSL_WMI_ProcessWMIEvent
                     */
                    if (item->itemType == AJ_WSL_WORKITEM(AJ_WSL_WORKITEM_SOCKET, WSL_NET_DATA_TX)) {
                        wsl_work_item** ppWork;
                        wsl_work_item* sockWork;
                        sockWork = (wsl_work_item*)AJ_WSL_Malloc(sizeof(wsl_work_item));
                        memset(sockWork, 0, sizeof(wsl_work_item));
                        sockWork->itemType = item->itemType;
                        sockWork->endpoint = item->endpoint;
                        ppWork = &sockWork;
                        AJ_QueuePush(AJ_WSL_SOCKET_CONTEXT[i].workRxQueue, ppWork, AJ_TIMER_FOREVER);
                    }
                    AJ_WSL_WMI_FreeWorkItem(item);
                }
            } while (1);
        }
        if (!g_b_spi_interrupt_data_ready) {
            AJ_YieldCurrentTask();
        }
        g_b_spi_interrupt_data_ready = FALSE; // reset the state of the interrupt signal
    }
}