1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/soft_spi:fix soft spi transfer bug

This commit is contained in:
xuke 2021-03-08 14:23:29 +08:00
parent 8ca676aa6e
commit 0c39c2321f

View File

@ -30,6 +30,7 @@
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #include "debug.h"
#define READ_PADDING_BYTE (0x00)
/** /**
* @brief Allocate one lock per SPI device * @brief Allocate one lock per SPI device
*/ */
@ -79,7 +80,7 @@ void soft_spi_init_pins(soft_spi_t bus)
gpio_clear(soft_spi_config[bus].mosi_pin); gpio_clear(soft_spi_config[bus].mosi_pin);
} }
if (gpio_is_valid(soft_spi_config[bus].miso_pin)) { if (gpio_is_valid(soft_spi_config[bus].miso_pin)) {
gpio_init(soft_spi_config[bus].mosi_pin, GPIO_IN); gpio_init(soft_spi_config[bus].miso_pin, GPIO_IN);
} }
} }
@ -137,29 +138,35 @@ void soft_spi_release(soft_spi_t bus)
static inline uint8_t _transfer_one_byte(soft_spi_t bus, uint8_t out) static inline uint8_t _transfer_one_byte(soft_spi_t bus, uint8_t out)
{ {
int8_t bit = 0, i = 0; uint8_t i = 8;
if (SOFT_SPI_MODE_1 == soft_spi_config[bus].soft_spi_mode || if (SOFT_SPI_MODE_1 == soft_spi_config[bus].soft_spi_mode ||
SOFT_SPI_MODE_3 == soft_spi_config[bus].soft_spi_mode) { SOFT_SPI_MODE_3 == soft_spi_config[bus].soft_spi_mode) {
/* CPHA = 1*/ /* CPHA = 1*/
gpio_toggle(soft_spi_config[bus].clk_pin); gpio_toggle(soft_spi_config[bus].clk_pin);
} }
bit = (out & (1 << 7)) >> 7; do {
gpio_write(soft_spi_config[bus].mosi_pin, bit); uint8_t bit = out >> 7;
for (i = 6; i >= 0; i--) {
xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk);
gpio_toggle(soft_spi_config[bus].clk_pin);
xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk);
gpio_toggle(soft_spi_config[bus].clk_pin);
bit = (out & (1 << i)) >> i;
gpio_write(soft_spi_config[bus].mosi_pin, bit); gpio_write(soft_spi_config[bus].mosi_pin, bit);
}
xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk); xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk);
gpio_toggle(soft_spi_config[bus].clk_pin); gpio_toggle(soft_spi_config[bus].clk_pin);
out <<= 1; /*shift transfer register*/
bit = gpio_read(soft_spi_config[bus].miso_pin);
out = bit ? (out | 0x01) : (out & 0xfe); /*set or delete bit 0*/
xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk);
--i;
if (i > 0) {
gpio_toggle(soft_spi_config[bus].clk_pin);
}
} while (i > 0);
if (SOFT_SPI_MODE_0 == soft_spi_config[bus].soft_spi_mode || if (SOFT_SPI_MODE_0 == soft_spi_config[bus].soft_spi_mode ||
SOFT_SPI_MODE_2 == soft_spi_config[bus].soft_spi_mode) { SOFT_SPI_MODE_2 == soft_spi_config[bus].soft_spi_mode) {
/* CPHASE = 1 */ /* CPHA = 0 */
xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk); xtimer_nanosleep(soft_spi_config[bus].soft_spi_clk);
gpio_toggle(soft_spi_config[bus].clk_pin); gpio_toggle(soft_spi_config[bus].clk_pin);
} }
@ -191,22 +198,40 @@ uint8_t soft_spi_transfer_byte(soft_spi_t bus, soft_spi_cs_t cs, bool cont, uint
} }
void soft_spi_transfer_bytes(soft_spi_t bus, soft_spi_cs_t cs, bool cont, void soft_spi_transfer_bytes(soft_spi_t bus, soft_spi_cs_t cs, bool cont,
const void *out, void *in, size_t len) const void *out, void *in, size_t len)
{ {
DEBUG("Soft SPI soft_spi_transfer_bytes\n"); DEBUG("Soft SPI soft_spi_transfer_bytes\n");
assert(soft_spi_bus_is_valid(bus)); assert(soft_spi_bus_is_valid(bus));
/* make sure at least one input or one output buffer is given */
assert(out || in);
uint8_t tmp = 0; const uint8_t *outbuf = out;
uint8_t *inbuf = in;
for (size_t i = 0; i < len-1; i++) { /* activate the given chip select line */
tmp = (NULL != out) ? ((uint8_t *)out)[i] : 0; if ((cs != GPIO_UNDEF) && (cs != SOFT_SPI_CS_UNDEF)) {
uint8_t retval = soft_spi_transfer_byte(bus, cs, true, tmp); gpio_clear((gpio_t)cs);
if (NULL != in) { }
((uint8_t *)in)[0] = retval;
if (!inbuf) {
for (size_t i = 0; i < len; i++) {
_transfer_one_byte(bus, outbuf[i]);
}
}
else if (!outbuf) {
for (size_t i = 0; i < len; i++) {
inbuf[i] = _transfer_one_byte(bus, READ_PADDING_BYTE);
}
}
else {
for (size_t i = 0; i < len; i++) {
inbuf[i] = _transfer_one_byte(bus, outbuf[i]);
} }
} }
tmp = (NULL != out) ? ((uint8_t *)out)[len-1] : 0; if (!cont) {
soft_spi_transfer_byte(bus, cs, cont, tmp); if ((cs != GPIO_UNDEF) && (cs != SOFT_SPI_CS_UNDEF)) {
gpio_set((gpio_t)cs);
}
}
} }