Exemple #1
0
static void spi_scan(SPI_MOSI *mosi, SPI_MISO *miso=&junk, int rbytes=0) {
	int i;
	
	assert(rbytes <= NSPI_RX);
	
	int tx_bytes = sizeof(SPI_MOSI);
    int tx_xfers = SPI_B2X(tx_bytes);
    
    int rx_bytes = sizeof(miso->status) + rbytes;
    int rx_xfers = SPI_B2X(rx_bytes);

    int arx_xfers = MAX(tx_xfers, prev->len_xfers);
    int arx_bytes = SPI_X2B(arx_xfers);

//jks
#if 0
static u4_t last_st;
static float acc_st, acc2_st;
static int big_rx;
if (arx_bytes > 1024) big_rx = 1;
u4_t st = timer_us();
float inc_st = (float) (st - last_st) / 1000.0;
acc_st += inc_st;
if (mosi->cmd == CmdSetWFFreq) acc2_st = 0;
printf("SCAN +%.3f %6.3f %6.3f %12s %16s tx(%dX=%dB) rx(%dX=%dB) arx(%dX=%dB)\n",
inc_st, acc_st, acc2_st, TaskName(), cmds[mosi->cmd], tx_xfers, tx_bytes, rx_xfers, rx_bytes, arx_xfers, arx_bytes);
if (mosi->cmd == CmdDuplex && big_rx) {
	acc_st = 0;
	big_rx = 0;
} else {
}
acc2_st += inc_st;
last_st = st;
#endif

//memset(miso, 0xee, sizeof(*miso));

    miso->len_xfers = rx_xfers;
    miso->cmd = mosi->cmd;
    rx_xfers = arx_xfers;

	if (mosi->cmd == CmdDuplex) mosi->cmd = CmdDummy;
	if (mosi->cmd == CmdNoDuplex) mosi->cmd = CmdDummy;

    for (;;) {
        peri_spi(SPI_HOST,
            mosi->msg, tx_xfers,   // MOSI: new request
            prev->msg, rx_xfers);  // MISO: response to previous caller's request
        evSpi(EV_SPILOOP, "spiScan", "peri_spi done");

		// fixme: understand why is this needed (hangs w/o it)
        if (spi_delay) spin_us(spi_delay); else usleep(10);
        evSpi(EV_SPILOOP, "spiScan", "spin_us done");
        if (prev->status != BUSY) break; // new request accepted?
        evSpi(EV_SPILOOP, "spiScan", "BUSY -> NextTask");
        NextTaskL("spi_scan"); // wait and try again
    }
    
    //jks
    #if 0
    printf("RX %d: ", prev->len_xfers);
    if (prev == &junk) {
    	printf("(junk) ");
    } else {
    	printf("%s ", cmds[prev->cmd]);
    }
	for (i=0; i<(prev->len_xfers+10); i++) {
		printf("%d:", i);
		#ifdef SPI_8
		printf("%02x ", prev->msg[i]);
		#endif
		#ifdef SPI_16
		printf("%04x ", prev->msg[i]);
		#endif
		#ifdef SPI_32
		printf("%08x ", prev->msg[i]);
		#endif
	}
    printf("\n");
    #endif

	u4_t status = prev->status;
    prev = miso; // next caller collects this for us
pcmd=mosi->cmd;

	//if (status & 0x0fff)
	//printf("st %04x\n", status);
	//if (mosi->cmd == CmdGetRXCount) printf("C");
	//if (mosi->cmd == CmdGetRX) printf("GRX\n");
	static int ff;
	if (status & (1<<SPI_SFT)) {
		rx0_wakeup = 1;
		evSnd(EV_SND, "wakeup", "");
		//printf(".");
		ff = 0;
	} else {
		rx0_wakeup = 0;
		if (!ff) {
			//printf(".");
			ff = 1;
		}
	}
	
	// process rx channel wakeup bits
	for (i=0; i<RX_CHANS; i++) {
		u4_t ch = 1<<(i+SPI_SFT);
		conn_t *c;
		if (status & ch) {
			c = &conns[i*2];
			assert(c->type == STREAM_SOUND);
			//if (c->task && !c->stop_data) printf("wakeup %d\n", c->task);
			//if (c->task && !c->stop_data) { printf("%d:%d ", i, c->task); fflush(stdout); }
			if (c->task && !c->stop_data) TaskWakeup(c->task, FALSE, 0);
		}
	}
}
void spi_dev(SPI_SEL sel, SPI_MOSI *mosi, int tx_xfers, SPI_MISO *miso, int rx_xfers)
{
    int rx=0, tx=0;
    u4_t stat;
    SPI_T *txb = mosi->msg;
    SPI_T *rxb = miso->msg;
    
    assert(init);

	if (sel == SPI_BOOT) {
		GPIO_CLR_BIT(SPI0_CS1);
	}
	
	evSpiDev(EC_EVENT, EV_SPILOOP, -1, "spi_dev", evprintf("%s(%d) T%dx R%dx", (sel != SPI_HOST)? "BOOT" : cmds[mosi->data.cmd], mosi->data.cmd, tx_xfers, rx_xfers));

	if (use_spidev) {
		int spi_bytes = SPI_X2B(MAX(tx_xfers, rx_xfers));
		struct spi_ioc_transfer spi_tr;
		memset(&spi_tr, 0, sizeof spi_tr);
		spi_tr.tx_buf = (unsigned long) txb;
		spi_tr.rx_buf = (unsigned long) rxb;
		spi_tr.len = spi_bytes;
		spi_tr.delay_usecs = 0;
		spi_tr.speed_hz = speed;
		spi_tr.bits_per_word = SPI_BPW;		// zero also means 8-bits?
		spi_tr.cs_change = 0;
	
		int actual_rxbytes;
		if ((actual_rxbytes = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &spi_tr)) < 0) sys_panic("SPI_IOC_MESSAGE");
		check(actual_rxbytes == spi_bytes);
		if (actual_rxbytes != spi_bytes) printf("actual_rxbytes %d spi_bytes %d\n", actual_rxbytes, spi_bytes);
	} else {
		SPI0_CONF = FORCE | SPI_CONF(spi_clkg, spi_speed);		// add FORCE
		SPI0_CTRL = EN;
	
		static char pbuf[65536];
		char *p = pbuf;
		int evp_spi;
		#if defined(EV_MEAS_SPI_DEV) || defined(SPI_PUMP_CHECK)
			evp_spi = (sel == SPI_HOST);
		#else
			evp_spi = 0;
		#endif
		int evp = evp_spi;
		if (evp) p += sprintf(p, "T %p %p %d R %p %p %d ", mosi, txb, tx_xfers, miso, rxb, rx_xfers);
	
		while (tx < tx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & TX_FULL)) {
				if (evp) p += sprintf(p, "TA%d:%x ", tx, txb[tx]);
				SPI0_TX = txb[tx++];		// move data only if FIFOs are able to accept
			}
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RA%d:%x ", rx-1, rxb[rx-1]);
			}
		}
		// at this point all tx data in FIFO but rx data may or may not have been moved out of FIFO
		// if necessary send dummy tx words to force larger number of rx words to be pulled through
		while (tx < rx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & TX_FULL)) {
				if (evp) p += sprintf(p, "TB%d:Z ", tx);
				SPI0_TX = 0; tx++;
			}
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RB%d:%x ", rx-1, rxb[rx-1]);
			}
			if (tx == 8 && evp) {
				p += sprintf(p, "... ");
				evp = 0;
			}
			if (tx == (rx_xfers-3)) evp = evp_spi;
		}
			evp = evp_spi;
		
		// handles the case of the FIFOs being slightly out-of-sync given that
		// tx/rx words moved must eventually be equal
		#ifdef SPI_32XXX
		int spin=0, rfull=0;
		while (rx < rx_xfers) {
			stat = SPI0_STAT;
			if (stat & RX_FULL) rfull++;
			spin++;
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RC%d:%x ", rx-1, rxb[rx-1]);
				spin=0;
			}
			if ((rx == (rx_xfers-1)) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				rxb[rx++] = SPI0_RX;	// last doesn't show in fifo flags
				if (evp) p += sprintf(p, "RL%d:%x ", rx-1, rxb[rx-1]);
			}
			if ((spin > 1024) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				printf("%s STUCK: rfull %d rx %d rx_xfers %d stat %02x\n", TaskName(), rfull, rx, rx_xfers, stat);
				while (rx < rx_xfers) {
					rxb[rx++] = SPI0_RX;
				}
				break;
			}
		}
		#else
		while (rx < rx_xfers) {
			stat = SPI0_STAT;
			if (!(stat & RX_EMPTY)) {
				rxb[rx++] = SPI0_RX;
				if (evp) p += sprintf(p, "RC%d:%x ", rx-1, rxb[rx-1]);
			}
			if ((rx == (rx_xfers-1)) && ((stat & (EOT|RXS)) == (EOT|RXS))) {
				rxb[rx++] = SPI0_RX;	// last doesn't show in fifo flags
				if (evp) p += sprintf(p, "RL%d:%x ", rx-1, rxb[rx-1]);
			}
		}
		#endif
	
		if (evp) evSpiDev(EC_EVENT, EV_SPILOOP, -1, "spi_dev", evprintf("%s", pbuf));
	
		while ((SPI0_STAT & TX_EMPTY) == 0)		// FIXME: needed for 6 MHz case, why?
			;
	
		while ((SPI0_STAT & EOT) == 0)		// FIXME: really needed?
			;
	
		SPI0_CTRL = 0;
		SPI0_CONF = SPI_CONF(spi_clkg, spi_speed);		// remove FORCE
	}

	if (sel == SPI_BOOT) {
		GPIO_SET_BIT(SPI0_CS1);
	}
}