SPI implement transaction locking
Use transactions to skip mutex locks for reads and writes
This commit is contained in:
parent
9bd5de11a7
commit
d0232d126a
@ -517,41 +517,24 @@ uint8_t spiTransferByte(spi_t * spi, uint8_t data)
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t __spiTranslate16(uint16_t data, bool msb)
|
uint32_t __spiTranslate24(uint32_t data)
|
||||||
{
|
{
|
||||||
if(msb) {
|
|
||||||
return (data >> 8) | (data << 8);
|
|
||||||
} else {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t __spiTranslate24(uint32_t data, bool msb)
|
|
||||||
{
|
|
||||||
if(msb) {
|
|
||||||
union {
|
union {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
uint8_t b[4];
|
uint8_t b[4];
|
||||||
} out;
|
} out;
|
||||||
out.l = data;
|
out.l = data;
|
||||||
return out.b[2] | (out.b[1] << 8) | (out.b[0] << 16);
|
return out.b[2] | (out.b[1] << 8) | (out.b[0] << 16);
|
||||||
} else {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t __spiTranslate32(uint32_t data, bool msb)
|
uint32_t __spiTranslate32(uint32_t data)
|
||||||
{
|
{
|
||||||
if(msb) {
|
|
||||||
union {
|
union {
|
||||||
uint32_t l;
|
uint32_t l;
|
||||||
uint8_t b[4];
|
uint8_t b[4];
|
||||||
} out;
|
} out;
|
||||||
out.l = data;
|
out.l = data;
|
||||||
return out.b[3] | (out.b[2] << 8) | (out.b[1] << 16) | (out.b[0] << 24);
|
return out.b[3] | (out.b[2] << 8) | (out.b[1] << 16) | (out.b[0] << 24);
|
||||||
} else {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiWriteWord(spi_t * spi, uint16_t data)
|
void spiWriteWord(spi_t * spi, uint16_t data)
|
||||||
@ -559,10 +542,13 @@ void spiWriteWord(spi_t * spi, uint16_t data)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
data = (data >> 8) | (data << 8);
|
||||||
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
spi->dev->data_buf[0] = __spiTranslate16(data, !spi->dev->ctrl.wr_bit_order);
|
spi->dev->data_buf[0] = data;
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -573,14 +559,20 @@ uint16_t spiTransferWord(spi_t * spi, uint16_t data)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
data = (data >> 8) | (data << 8);
|
||||||
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
||||||
spi->dev->data_buf[0] = __spiTranslate16(data, !spi->dev->ctrl.wr_bit_order);
|
spi->dev->data_buf[0] = data;
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = __spiTranslate16(spi->dev->data_buf[0] & 0xFFFF, !spi->dev->ctrl.rd_bit_order);
|
data = spi->dev->data_buf[0];
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
|
if(!spi->dev->ctrl.rd_bit_order){
|
||||||
|
data = (data >> 8) | (data << 8);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,10 +581,13 @@ void spiWriteLong(spi_t * spi, uint32_t data)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
data = __spiTranslate32(data);
|
||||||
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
spi->dev->data_buf[0] = __spiTranslate32(data, !spi->dev->ctrl.wr_bit_order);
|
spi->dev->data_buf[0] = data;
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
@ -603,59 +598,23 @@ uint32_t spiTransferLong(spi_t * spi, uint32_t data)
|
|||||||
if(!spi) {
|
if(!spi) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
data = __spiTranslate32(data);
|
||||||
|
}
|
||||||
SPI_MUTEX_LOCK();
|
SPI_MUTEX_LOCK();
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
||||||
spi->dev->data_buf[0] = __spiTranslate32(data, !spi->dev->ctrl.wr_bit_order);
|
spi->dev->data_buf[0] = data;
|
||||||
spi->dev->cmd.usr = 1;
|
spi->dev->cmd.usr = 1;
|
||||||
while(spi->dev->cmd.usr);
|
while(spi->dev->cmd.usr);
|
||||||
data = __spiTranslate32(spi->dev->data_buf[0], !spi->dev->ctrl.rd_bit_order);
|
data = spi->dev->data_buf[0];
|
||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
|
if(!spi->dev->ctrl.rd_bit_order){
|
||||||
|
data = __spiTranslate32(data);
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
|
|
||||||
{
|
|
||||||
if(!spi) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bits > 32) {
|
|
||||||
bits = 32;
|
|
||||||
}
|
|
||||||
uint32_t bytes = (bits + 7) / 8;//64 max
|
|
||||||
uint32_t mask = (((uint64_t)1 << bits) - 1) & 0xFFFFFFFF;
|
|
||||||
|
|
||||||
SPI_MUTEX_LOCK();
|
|
||||||
spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1);
|
|
||||||
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
|
|
||||||
if(bytes == 1) {
|
|
||||||
spi->dev->data_buf[0] = data & mask;
|
|
||||||
} else if(bytes == 2) {
|
|
||||||
spi->dev->data_buf[0] = __spiTranslate16(data & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
} else if(bytes == 3) {
|
|
||||||
spi->dev->data_buf[0] = __spiTranslate24(data & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
} else {
|
|
||||||
spi->dev->data_buf[0] = __spiTranslate32(data & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
}
|
|
||||||
spi->dev->cmd.usr = 1;
|
|
||||||
|
|
||||||
while(spi->dev->cmd.usr);
|
|
||||||
|
|
||||||
if(out) {
|
|
||||||
if(bytes == 1) {
|
|
||||||
*out = spi->dev->data_buf[0] & mask;
|
|
||||||
} else if(bytes == 2) {
|
|
||||||
*out = __spiTranslate16(spi->dev->data_buf[0] & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
} else if(bytes == 3) {
|
|
||||||
*out = __spiTranslate24(spi->dev->data_buf[0] & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
} else {
|
|
||||||
*out = __spiTranslate32(spi->dev->data_buf[0] & mask, !spi->dev->ctrl.wr_bit_order);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SPI_MUTEX_UNLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t bytes)
|
void __spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t bytes)
|
||||||
{
|
{
|
||||||
if(!spi) {
|
if(!spi) {
|
||||||
@ -721,6 +680,320 @@ void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size)
|
|||||||
SPI_MUTEX_UNLOCK();
|
SPI_MUTEX_UNLOCK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Manual Lock Management
|
||||||
|
* */
|
||||||
|
|
||||||
|
#define MSB_32_SET(var, val) { uint8_t * d = (uint8_t *)&(val); (var) = d[3] | (d[2] << 8) | (d[1] << 16) | (d[0] << 24); }
|
||||||
|
#define MSB_24_SET(var, val) { uint8_t * d = (uint8_t *)&(val); (var) = d[2] | (d[1] << 8) | (d[0] << 16); }
|
||||||
|
#define MSB_16_SET(var, val) { (var) = (((val) & 0xFF00) >> 8) | (((val) & 0xFF) << 8); }
|
||||||
|
|
||||||
|
void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SPI_MUTEX_LOCK();
|
||||||
|
spi->dev->clock.val = clockDiv;
|
||||||
|
switch (dataMode) {
|
||||||
|
case SPI_MODE1:
|
||||||
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
|
spi->dev->user.ck_out_edge = 1;
|
||||||
|
break;
|
||||||
|
case SPI_MODE2:
|
||||||
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
|
spi->dev->user.ck_out_edge = 0;
|
||||||
|
break;
|
||||||
|
case SPI_MODE3:
|
||||||
|
spi->dev->pin.ck_idle_edge = 1;
|
||||||
|
spi->dev->user.ck_out_edge = 1;
|
||||||
|
break;
|
||||||
|
case SPI_MODE0:
|
||||||
|
default:
|
||||||
|
spi->dev->pin.ck_idle_edge = 0;
|
||||||
|
spi->dev->user.ck_out_edge = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (SPI_MSBFIRST == bitOrder) {
|
||||||
|
spi->dev->ctrl.wr_bit_order = 0;
|
||||||
|
spi->dev->ctrl.rd_bit_order = 0;
|
||||||
|
} else if (SPI_LSBFIRST == bitOrder) {
|
||||||
|
spi->dev->ctrl.wr_bit_order = 1;
|
||||||
|
spi->dev->ctrl.rd_bit_order = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiSimpleTransaction(spi_t * spi)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SPI_MUTEX_LOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiEndTransaction(spi_t * spi)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SPI_MUTEX_UNLOCK();
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiWriteByteNL(spi_t * spi, uint8_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 7;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 7;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
data = spi->dev->data_buf[0] & 0xFF;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiWriteShortNL(spi_t * spi, uint16_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
MSB_16_SET(data, data);
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
MSB_16_SET(data, data);
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 15;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 15;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
data = spi->dev->data_buf[0] & 0xFFFF;
|
||||||
|
if(!spi->dev->ctrl.rd_bit_order){
|
||||||
|
MSB_16_SET(data, data);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiWriteLongNL(spi_t * spi, uint32_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
MSB_32_SET(data, data);
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t spiTransferLongNL(spi_t * spi, uint32_t data)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
MSB_32_SET(data, data);
|
||||||
|
}
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = 31;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 31;
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
data = spi->dev->data_buf[0];
|
||||||
|
if(!spi->dev->ctrl.rd_bit_order){
|
||||||
|
MSB_32_SET(data, data);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiWriteNL(spi_t * spi, const void * data_in, size_t len){
|
||||||
|
size_t longs = len >> 2;
|
||||||
|
if(len & 3){
|
||||||
|
longs++;
|
||||||
|
}
|
||||||
|
uint32_t * data = (uint32_t*)data_in;
|
||||||
|
size_t c_len = 0, c_longs = 0;
|
||||||
|
|
||||||
|
while(len){
|
||||||
|
c_len = (len>64)?64:len;
|
||||||
|
c_longs = (longs > 16)?16:longs;
|
||||||
|
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
for (int i=0; i<c_longs; i++) {
|
||||||
|
spi->dev->data_buf[i] = data[i];
|
||||||
|
}
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
|
||||||
|
data += c_longs;
|
||||||
|
longs -= c_longs;
|
||||||
|
len -= c_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, size_t len){
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t longs = len >> 2;
|
||||||
|
if(len & 3){
|
||||||
|
longs++;
|
||||||
|
}
|
||||||
|
uint32_t * data = (uint32_t*)data_in;
|
||||||
|
uint32_t * result = (uint32_t*)data_out;
|
||||||
|
size_t c_len = 0, c_longs = 0;
|
||||||
|
|
||||||
|
while(len){
|
||||||
|
c_len = (len>64)?64:len;
|
||||||
|
c_longs = (longs > 16)?16:longs;
|
||||||
|
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = (c_len*8)-1;
|
||||||
|
if(data){
|
||||||
|
for (int i=0; i<c_longs; i++) {
|
||||||
|
spi->dev->data_buf[i] = data[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i=0; i<c_longs; i++) {
|
||||||
|
spi->dev->data_buf[i] = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
if(result){
|
||||||
|
for (int i=0; i<c_longs; i++) {
|
||||||
|
result[i] = spi->dev->data_buf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(data){
|
||||||
|
data += c_longs;
|
||||||
|
}
|
||||||
|
if(result){
|
||||||
|
result += c_longs;
|
||||||
|
}
|
||||||
|
longs -= c_longs;
|
||||||
|
len -= c_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
|
||||||
|
{
|
||||||
|
if(!spi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bits > 32) {
|
||||||
|
bits = 32;
|
||||||
|
}
|
||||||
|
uint32_t bytes = (bits + 7) / 8;//64 max
|
||||||
|
uint32_t mask = (((uint64_t)1 << bits) - 1) & 0xFFFFFFFF;
|
||||||
|
data = data & mask;
|
||||||
|
if(!spi->dev->ctrl.wr_bit_order){
|
||||||
|
if(bytes == 2) {
|
||||||
|
MSB_16_SET(data, data);
|
||||||
|
} else if(bytes == 3) {
|
||||||
|
MSB_24_SET(data, data);
|
||||||
|
} else {
|
||||||
|
MSB_32_SET(data, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1);
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1);
|
||||||
|
spi->dev->data_buf[0] = data;
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
data = spi->dev->data_buf[0];
|
||||||
|
if(out) {
|
||||||
|
*out = data;
|
||||||
|
if(!spi->dev->ctrl.rd_bit_order){
|
||||||
|
if(bytes == 2) {
|
||||||
|
MSB_16_SET(*out, data);
|
||||||
|
} else if(bytes == 3) {
|
||||||
|
MSB_24_SET(*out, data);
|
||||||
|
} else {
|
||||||
|
MSB_32_SET(*out, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){
|
||||||
|
size_t longs = len >> 2;
|
||||||
|
if(len & 3){
|
||||||
|
longs++;
|
||||||
|
}
|
||||||
|
bool msb = !spi->dev->ctrl.wr_bit_order;
|
||||||
|
uint32_t * data = (uint32_t*)data_in;
|
||||||
|
size_t c_len = 0, c_longs = 0, l_bytes = 0;
|
||||||
|
|
||||||
|
while(len){
|
||||||
|
c_len = (len>64)?64:len;
|
||||||
|
c_longs = (longs > 16)?16:longs;
|
||||||
|
l_bytes = (c_len & 3);
|
||||||
|
|
||||||
|
spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1;
|
||||||
|
spi->dev->miso_dlen.usr_miso_dbitlen = 0;
|
||||||
|
for (int i=0; i<c_longs; i++) {
|
||||||
|
if(msb){
|
||||||
|
if(l_bytes && i == (c_longs - 1)){
|
||||||
|
if(l_bytes == 2){
|
||||||
|
MSB_16_SET(spi->dev->data_buf[i], data[i]);
|
||||||
|
} else {
|
||||||
|
spi->dev->data_buf[i] = data[i] & 0xFF;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MSB_32_SET(spi->dev->data_buf[i], data[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spi->dev->data_buf[i] = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spi->dev->cmd.usr = 1;
|
||||||
|
while(spi->dev->cmd.usr);
|
||||||
|
|
||||||
|
data += c_longs;
|
||||||
|
longs -= c_longs;
|
||||||
|
len -= c_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clock Calculators
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t regValue;
|
uint32_t regValue;
|
||||||
@ -795,5 +1068,3 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
|
|||||||
return bestReg.regValue;
|
return bestReg.regValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,12 +85,15 @@ void spiSSClear(spi_t * spi);
|
|||||||
void spiWaitReady(spi_t * spi);
|
void spiWaitReady(spi_t * spi);
|
||||||
|
|
||||||
uint32_t spiGetClockDiv(spi_t * spi);
|
uint32_t spiGetClockDiv(spi_t * spi);
|
||||||
void spiSetClockDiv(spi_t * spi, uint32_t clockDiv);
|
|
||||||
|
|
||||||
uint8_t spiGetDataMode(spi_t * spi);
|
uint8_t spiGetDataMode(spi_t * spi);
|
||||||
void spiSetDataMode(spi_t * spi, uint8_t dataMode);
|
|
||||||
|
|
||||||
uint8_t spiGetBitOrder(spi_t * spi);
|
uint8_t spiGetBitOrder(spi_t * spi);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non transaction based lock methods (each locks and unlocks when called)
|
||||||
|
* */
|
||||||
|
void spiSetClockDiv(spi_t * spi, uint32_t clockDiv);
|
||||||
|
void spiSetDataMode(spi_t * spi, uint8_t dataMode);
|
||||||
void spiSetBitOrder(spi_t * spi, uint8_t bitOrder);
|
void spiSetBitOrder(spi_t * spi, uint8_t bitOrder);
|
||||||
|
|
||||||
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len);
|
void spiWrite(spi_t * spi, uint32_t *data, uint8_t len);
|
||||||
@ -102,10 +105,32 @@ void spiTransfer(spi_t * spi, uint32_t *out, uint8_t len);
|
|||||||
uint8_t spiTransferByte(spi_t * spi, uint8_t data);
|
uint8_t spiTransferByte(spi_t * spi, uint8_t data);
|
||||||
uint16_t spiTransferWord(spi_t * spi, uint16_t data);
|
uint16_t spiTransferWord(spi_t * spi, uint16_t data);
|
||||||
uint32_t spiTransferLong(spi_t * spi, uint32_t data);
|
uint32_t spiTransferLong(spi_t * spi, uint32_t data);
|
||||||
|
|
||||||
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits);
|
|
||||||
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size);
|
void spiTransferBytes(spi_t * spi, uint8_t * data, uint8_t * out, uint32_t size);
|
||||||
|
void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New (EXPERIMENTAL) Transaction lock based API (lock once until endTransaction)
|
||||||
|
* */
|
||||||
|
void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder);
|
||||||
|
void spiSimpleTransaction(spi_t * spi);
|
||||||
|
void spiEndTransaction(spi_t * spi);
|
||||||
|
|
||||||
|
void spiWriteNL(spi_t * spi, const void * data, uint32_t len);
|
||||||
|
void spiWriteByteNL(spi_t * spi, uint8_t data);
|
||||||
|
void spiWriteShortNL(spi_t * spi, uint16_t data);
|
||||||
|
void spiWriteLongNL(spi_t * spi, uint32_t data);
|
||||||
|
void spiWritePixelsNL(spi_t * spi, const void * data, uint32_t len);
|
||||||
|
|
||||||
|
#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len)
|
||||||
|
uint8_t spiTransferByteNL(spi_t * spi, uint8_t data);
|
||||||
|
uint16_t spiTransferShortNL(spi_t * spi, uint16_t data);
|
||||||
|
uint32_t spiTransferLongNL(spi_t * spi, uint32_t data);
|
||||||
|
void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, uint32_t len);
|
||||||
|
void spiTransferBitsNL(spi_t * spi, uint32_t data_in, uint32_t * data_out, uint8_t bits);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions to translate frequency to clock divider and back
|
||||||
|
* */
|
||||||
uint32_t spiFrequencyToClockDiv(uint32_t freq);
|
uint32_t spiFrequencyToClockDiv(uint32_t freq);
|
||||||
uint32_t spiClockDivToFrequency(uint32_t freq);
|
uint32_t spiClockDivToFrequency(uint32_t freq);
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ SPIClass::SPIClass(uint8_t spi_bus)
|
|||||||
,_ss(-1)
|
,_ss(-1)
|
||||||
,_div(0)
|
,_div(0)
|
||||||
,_freq(1000000)
|
,_freq(1000000)
|
||||||
|
, _inTransaction(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
|
void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
|
||||||
@ -84,16 +85,6 @@ void SPIClass::setHwCs(bool use)
|
|||||||
_use_hw_ss = use;
|
_use_hw_ss = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::beginTransaction(SPISettings settings)
|
|
||||||
{
|
|
||||||
spiWaitReady(_spi);
|
|
||||||
setFrequency(settings._clock);
|
|
||||||
setBitOrder(settings._bitOrder);
|
|
||||||
setDataMode(settings._dataMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SPIClass::endTransaction() {}
|
|
||||||
|
|
||||||
void SPIClass::setFrequency(uint32_t freq)
|
void SPIClass::setFrequency(uint32_t freq)
|
||||||
{
|
{
|
||||||
//check if last freq changed
|
//check if last freq changed
|
||||||
@ -121,38 +112,79 @@ void SPIClass::setBitOrder(uint8_t bitOrder)
|
|||||||
spiSetBitOrder(_spi, bitOrder);
|
spiSetBitOrder(_spi, bitOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPIClass::beginTransaction(SPISettings settings)
|
||||||
|
{
|
||||||
|
//check if last freq changed
|
||||||
|
uint32_t cdiv = spiGetClockDiv(_spi);
|
||||||
|
if(_freq != settings._clock || _div != cdiv) {
|
||||||
|
_freq = settings._clock;
|
||||||
|
_div = spiFrequencyToClockDiv(_freq);
|
||||||
|
}
|
||||||
|
spiTransaction(_spi, _div, settings._dataMode, settings._bitOrder);
|
||||||
|
_inTransaction = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPIClass::endTransaction()
|
||||||
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
spiEndTransaction(_spi);
|
||||||
|
_inTransaction = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SPIClass::write(uint8_t data)
|
void SPIClass::write(uint8_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiWriteByteNL(_spi, data);
|
||||||
|
}
|
||||||
spiWriteByte(_spi, data);
|
spiWriteByte(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t SPIClass::transfer(uint8_t data)
|
uint8_t SPIClass::transfer(uint8_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiTransferByteNL(_spi, data);
|
||||||
|
}
|
||||||
return spiTransferByte(_spi, data);
|
return spiTransferByte(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::write16(uint16_t data)
|
void SPIClass::write16(uint16_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiWriteShortNL(_spi, data);
|
||||||
|
}
|
||||||
spiWriteWord(_spi, data);
|
spiWriteWord(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SPIClass::transfer16(uint16_t data)
|
uint16_t SPIClass::transfer16(uint16_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiTransferShortNL(_spi, data);
|
||||||
|
}
|
||||||
return spiTransferWord(_spi, data);
|
return spiTransferWord(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::write32(uint32_t data)
|
void SPIClass::write32(uint32_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiWriteLongNL(_spi, data);
|
||||||
|
}
|
||||||
spiWriteLong(_spi, data);
|
spiWriteLong(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SPIClass::transfer32(uint32_t data)
|
uint32_t SPIClass::transfer32(uint32_t data)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiTransferLongNL(_spi, data);
|
||||||
|
}
|
||||||
return spiTransferLong(_spi, data);
|
return spiTransferLong(_spi, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIClass::transferBits(uint32_t data, uint32_t * out, uint8_t bits)
|
void SPIClass::transferBits(uint32_t data, uint32_t * out, uint8_t bits)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiTransferBitsNL(_spi, data, out, bits);
|
||||||
|
}
|
||||||
spiTransferBits(_spi, data, out, bits);
|
spiTransferBits(_spi, data, out, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +197,12 @@ void SPIClass::transferBits(uint32_t data, uint32_t * out, uint8_t bits)
|
|||||||
*/
|
*/
|
||||||
void SPIClass::writeBytes(uint8_t * data, uint32_t size)
|
void SPIClass::writeBytes(uint8_t * data, uint32_t size)
|
||||||
{
|
{
|
||||||
spiTransferBytes(_spi, data, 0, size);
|
if(_inTransaction){
|
||||||
|
return spiWriteNL(_spi, data, size);
|
||||||
|
}
|
||||||
|
spiSimpleTransaction(_spi);
|
||||||
|
spiWriteNL(_spi, data, size);
|
||||||
|
spiEndTransaction(_spi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,6 +212,9 @@ void SPIClass::writeBytes(uint8_t * data, uint32_t size)
|
|||||||
*/
|
*/
|
||||||
void SPIClass::transferBytes(uint8_t * data, uint8_t * out, uint32_t size)
|
void SPIClass::transferBytes(uint8_t * data, uint8_t * out, uint32_t size)
|
||||||
{
|
{
|
||||||
|
if(_inTransaction){
|
||||||
|
return spiTransferBytesNL(_spi, data, out, size);
|
||||||
|
}
|
||||||
spiTransferBytes(_spi, data, out, size);
|
spiTransferBytes(_spi, data, out, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,19 @@ public:
|
|||||||
|
|
||||||
class SPIClass
|
class SPIClass
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
int8_t _spi_num;
|
||||||
|
spi_t * _spi;
|
||||||
|
bool _use_hw_ss;
|
||||||
|
int8_t _sck;
|
||||||
|
int8_t _miso;
|
||||||
|
int8_t _mosi;
|
||||||
|
int8_t _ss;
|
||||||
|
uint32_t _div;
|
||||||
|
uint32_t _freq;
|
||||||
|
bool _inTransaction;
|
||||||
|
void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SPIClass(uint8_t spi_bus=HSPI);
|
SPIClass(uint8_t spi_bus=HSPI);
|
||||||
void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
|
void begin(int8_t sck=-1, int8_t miso=-1, int8_t mosi=-1, int8_t ss=-1);
|
||||||
@ -61,17 +74,8 @@ public:
|
|||||||
void write32(uint32_t data);
|
void write32(uint32_t data);
|
||||||
void writeBytes(uint8_t * data, uint32_t size);
|
void writeBytes(uint8_t * data, uint32_t size);
|
||||||
void writePattern(uint8_t * data, uint8_t size, uint32_t repeat);
|
void writePattern(uint8_t * data, uint8_t size, uint32_t repeat);
|
||||||
private:
|
|
||||||
int8_t _spi_num;
|
spi_t * bus(){ return _spi; }
|
||||||
spi_t * _spi;
|
|
||||||
bool _use_hw_ss;
|
|
||||||
int8_t _sck;
|
|
||||||
int8_t _miso;
|
|
||||||
int8_t _mosi;
|
|
||||||
int8_t _ss;
|
|
||||||
uint32_t _div;
|
|
||||||
uint32_t _freq;
|
|
||||||
void writePattern_(uint8_t * data, uint8_t size, uint8_t repeat);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SPIClass SPI;
|
extern SPIClass SPI;
|
||||||
|
Loading…
Reference in New Issue
Block a user