コード例 #1
0
ファイル: spi.c プロジェクト: boydcase31/openiBoot
int spi_tx(int port, const uint8_t* buffer, int len, int block, int unknown) {
	if(port > (NUM_SPIPORTS - 1)) {
		return -1;
	}

	SET_REG(SPIRegs[port].control, GET_REG(SPIRegs[port].control) | (1 << 2));
	SET_REG(SPIRegs[port].control, GET_REG(SPIRegs[port].control) | (1 << 3));

	spi_info[port].txBuffer = buffer;

	if(len > MAX_TX_BUFFER)
		spi_info[port].txCurrentLen = MAX_TX_BUFFER;
	else
		spi_info[port].txCurrentLen = len;

	spi_info[port].txTotalLen = len;
	spi_info[port].txDone = FALSE;

	if(unknown == 0) {
		SET_REG(SPIRegs[port].cnt, 0);
	}

	spi_txdata(port, buffer, 0, spi_info[port].txCurrentLen);

	SET_REG(SPIRegs[port].control, 1);

	if(block) {
		while(!spi_info[port].txDone || GET_BITS(GET_REG(SPIRegs[port].status), 4, 4) != 0) {
			// yield
		}
		return len;
	} else {
		return 0;
	}
}
コード例 #2
0
ファイル: spi.c プロジェクト: chronzz/openiBoot
int spi_tx(int port, const uint8_t* buffer, int len, int block, int unknown)
{
    if(port >= SPICount || port < 0)
        return -1;

    SPIStruct *spi = &SPIData[port];

    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 2));
    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 3));

    // Set len to number of words.
    len = (len + ((1<<spi->wordSize)-1)) >> spi->wordSize;

    spi->txBuffer = (void*)buffer;
    spi->rxBuffer = NULL;
    spi->txLength = len;

    if(len > MAX_TX_BUFFER)
        spi->txDone = MAX_TX_BUFFER;
    else
        spi->txDone = len;

    if(unknown == 0) {
        SET_REG(spi->registers->rxCount, 0);
    }
    else
    {
        spi->config |= 0x80;
    }

    //bufferPrintf("spi_tx(%d, %p, %d, %d, %d)\n", port, buffer, len, block, unknown);

    spi_txdata(spi, buffer, 0, spi->txDone);

    spi->config |= 0x200100;
    SET_REG(spi->registers->txCount, len);
    SET_REG(spi->registers->config, spi->config);
    SET_REG(spi->registers->control, 1);

    if(block)
    {
        while(spi->txBuffer != NULL || TX_BUFFER_LEFT(GET_REG(spi->registers->status)) > 0)
            task_yield();

        return len;
    }
    else
        return 0;
}
コード例 #3
0
ファイル: spi.c プロジェクト: boydcase31/openiBoot
int spi_txrx(int port, const uint8_t* outBuffer, int outLen, uint8_t* inBuffer, int inLen, int block)
{
	if(port > (NUM_SPIPORTS - 1)) {
		return -1;
	}

	SET_REG(SPIRegs[port].control, GET_REG(SPIRegs[port].control) | (1 << 2));
	SET_REG(SPIRegs[port].control, GET_REG(SPIRegs[port].control) | (1 << 3));

	spi_info[port].txBuffer = outBuffer;

	if(outLen > MAX_TX_BUFFER)
		spi_info[port].txCurrentLen = MAX_TX_BUFFER;
	else
		spi_info[port].txCurrentLen = outLen;

	spi_info[port].txTotalLen = outLen;
	spi_info[port].txDone = FALSE;

	spi_info[port].rxBuffer = inBuffer;
	spi_info[port].rxDone = FALSE;
	spi_info[port].rxCurrentLen = 0;
	spi_info[port].rxTotalLen = inLen;
	spi_info[port].counter = 0;

	spi_txdata(port, outBuffer, 0, spi_info[port].txCurrentLen);

	SET_REG(SPIRegs[port].cnt, (inLen + ((1<<spi_info[port].wordSize)-1)) >> spi_info[port].wordSize);
	SET_REG(SPIRegs[port].control, 1);

	if(block) {
		while(!spi_info[port].txDone || !spi_info[port].rxDone || GET_BITS(GET_REG(SPIRegs[port].status), 4, 4) != 0) {
			// yield
		}
		return inLen;
	} else {
		return 0;
	}
}
コード例 #4
0
ファイル: spi.c プロジェクト: boydcase31/openiBoot
static void spiIRQHandler(uint32_t port) {
	if(port > (NUM_SPIPORTS - 1)) {
		return;
	}

	uint32_t status = GET_REG(SPIRegs[port].status);
	if(status & (1 << 3)) {
		spi_info[port].counter++;
	}

	if(status & (1 << 1)) {
		while(TRUE) {
			// take care of tx
			if(spi_info[port].txBuffer != NULL) {
				if(spi_info[port].txCurrentLen < spi_info[port].txTotalLen)
				{
					int toTX = spi_info[port].txTotalLen - spi_info[port].txCurrentLen;
					int canTX = (MAX_TX_BUFFER - TX_BUFFER_LEFT(status)) << spi_info[port].wordSize;

					if(toTX > canTX)
						toTX = canTX;

					spi_txdata(port, spi_info[port].txBuffer, spi_info[port].txCurrentLen, spi_info[port].txCurrentLen+toTX);
					spi_info[port].txCurrentLen += toTX;

				} else {
					spi_info[port].txDone = TRUE;
					spi_info[port].txBuffer = NULL;
				}
			}

dorx:
			// take care of rx
			if(spi_info[port].rxBuffer == NULL)
				break;

			int toRX = spi_info[port].rxTotalLen - spi_info[port].rxCurrentLen;
			int canRX = GET_BITS(status, 8, 4) << spi_info[port].wordSize;

			if(toRX > canRX)
				toRX = canRX;

			spi_rxdata(port, spi_info[port].rxBuffer, spi_info[port].rxCurrentLen, spi_info[port].rxCurrentLen+toRX);
			spi_info[port].rxCurrentLen += toRX;

			if(spi_info[port].rxCurrentLen < spi_info[port].rxTotalLen)
				break;

			spi_info[port].rxDone = TRUE;
			spi_info[port].rxBuffer = NULL;
		}


	} else  if(status & (1 << 0)) {
		// jump into middle of the loop to handle rx only, stupidly
		goto dorx;
	}

	// acknowledge interrupt handling complete
	SET_REG(SPIRegs[port].status, status);
}
コード例 #5
0
ファイル: spi.c プロジェクト: chronzz/openiBoot
static void spi_irq_handler(uint32_t i)
{
    SPIStruct *spi = &SPIData[i];
    uint32_t status = GET_REG(spi->registers->status);

    if((status & 1) && !(status & 0x400002))
        goto do_rx;
    else if(!(status & 0x400002))
        goto complete;

    while(TRUE)
    {
        if(spi->txBuffer != NULL)
        {
            uint32_t avail = MAX_TX_BUFFER - TX_BUFFER_LEFT(status);
            uint32_t left = spi->txLength - spi->txDone;
            if(avail > left)
                avail = left;

            spi_txdata(spi, spi->txBuffer, spi->txDone, spi->txDone + avail);

            spi->txDone += avail;
            if(spi->txDone >= spi->txLength)
            {
                spi->txBuffer = NULL;
                spi->txLength = 0;
                spi->txDone = 0;

                spi->config &=~ 0x200000;
                SET_REG(spi->registers->config, spi->config);
            }
        }

do_rx:
        if(spi->rxBuffer != NULL)
        {
            uint32_t avail = RX_BUFFER_LEFT(status);
            uint32_t left = spi->rxLength - spi->rxDone;
            if(avail > left)
                avail = left;

            if(avail > 0)
            {
                spi_rxdata(spi, spi->rxBuffer, spi->rxDone, spi->rxDone + avail);
                spi->rxDone += avail;
            }

            spi->rxDone += avail;

            if(spi->rxDone >= spi->rxLength)
            {
                spi->rxBuffer = NULL;
                spi->rxLength = 0;
                spi->rxDone = 0;

                spi->config &=~ 0x81;
                SET_REG(spi->registers->config, spi->config);
            }
        }

complete:
        if(spi->txBuffer == NULL && spi->rxBuffer == NULL)
        {
            spi->config &=~ 0x200181;
            SET_REG(spi->registers->config, spi->config);
            break;
        }
        else
            break;
    }

    SET_REG(spi->registers->status, status);
}