/** * DMA based block transfer to and from SPI devices * For RX, a buffer full of 0xFF must be transmitted to create the clock * For TX, an empty RX buffer must be provided for dummy RX data. * This only works with fixed chip-select * @param outbuf pointer to TX buffer * @param inbuf pointer to RX buffer * @param length Amount of bytes to transfer * @return return 0 if the SPI device was not ready, 1 otherwise. */ int spi_dma_transfer(spi_chip_t * spi_chip, uint8_t * outbuf, uint8_t * inbuf, uint32_t length) { unsigned int bytes_done = 0; /* Wait for SPI to become ready */ if (!spi_busy_wait_tx()) { xSemaphoreGive(spi_chip->spi_dev->lock); return 0; } /* Set chip select mode */ if (current_chip != spi_chip) { spi_setup_chip(spi_chip); current_chip = spi_chip; } /* Select chip */ SPI_MR = (SPI_MR & ~SPI_MR_PCS_MASK) | (spi_chip->cs << SPI_MR_PCS_BIT); /* Enable PDC interrupt on SPI */ SPI_IER = SPI_IER_TEND; /* Loop here if length is larger than 0xFFFF */ while (bytes_done < length) { /* Start PDC Transfer */ if (inbuf != NULL) PDC_MPR6 = (uint32_t) &inbuf[bytes_done]; PDC_MPR7 = (uint32_t) &outbuf[bytes_done]; /* Number of bytes to read - truncated to 64k */ if ((length - bytes_done) > 0x0000FFFF) { if (inbuf != NULL) PDC_TCR6 = 0x0000FFFF; PDC_TCR7 = 0x0000FFFF; bytes_done += 0x0000FFFF; } else { if (inbuf != NULL) PDC_TCR6 = length - bytes_done; PDC_TCR7 = length - bytes_done; bytes_done = length; } /* Wait for the DMA finish signal */ xSemaphoreTake(spi_sem_dma, 1*configTICK_RATE_HZ); } /* Disable PDC interrupt on SPI */ SPI_IER = SPI_IER_TEND; return 1; }
/* reference lm70 */ void accel_sensor_spi_setup_cs(spi_dev_t * spi_dev, spi_chip_t * spi_chip, uint8_t cs) { spi_chip->spi_dev = spi_dev; // A pointer to the physical device SPI0 spi_chip->baudrate = 1000000; // This is only initial baud rate, it will be increased by the driver spi_chip->spi_mode = 3; // SPI mode spi_chip->bits = 16; // Default value for transferring bytes spi_chip->cs = cs; // The chip select number spi_chip->reg = cs/4; // The chip select register, The register bank to use spi_chip->stay_act = 0; // Should the chip-select stay active until next SPI transmission? //reference lm70 spi_chip->spck_delay = 4; // Delay spi_chip->trans_delay = 60; // Delay spi_setup_chip(spi_chip); }
/** * Send a byte via SPI * @param spi_chip The chip to send to * @param 16 bits to send */ void spi_write(spi_chip_t * spi_chip, uint16_t byte) { spi_busy_wait_tx(); /* Re-initialise new chip in new mode */ if (current_chip != spi_chip) { spi_setup_chip(spi_chip); current_chip = spi_chip; } /* Select chip */ SPI_MR = (SPI_MR & ~SPI_MR_PCS_MASK) | (spi_chip->cs << SPI_MR_PCS_BIT); SPI_TDR = byte; }