Skip to content

Commit 1c33609

Browse files
marceloaqnotekka007
authored andcommitted
Fix SPIDEV on Armbian Stretch (#1200)
Fix #1195
1 parent 0b51d5c commit 1c33609

File tree

9 files changed

+177
-60
lines changed

9 files changed

+177
-60
lines changed

configure

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -193,51 +193,51 @@ function detect_machine {
193193
soc="BCM2837"
194194
fi
195195
;;
196-
sun4i|Sun4iw1p1)
196+
*sun4i*|*Sun4iw1p1*)
197197
soc="A10"
198198
;;
199-
sun5i|Sun4iw2p1)
199+
*sun5i*|*Sun4iw2p1*)
200200
soc="A13"
201201
;;
202-
Sun4iw2p2)
202+
*Sun4iw2p2*)
203203
soc="A12"
204204
;;
205-
Sun4iw2p3)
205+
*Sun4iw2p3*)
206206
soc="A10s"
207207
;;
208-
sun6i|Sun8iw1p1)
208+
*sun6i*|*Sun8iw1p1*)
209209
soc="A31"
210210
;;
211-
Sun8iw1p2)
211+
*Sun8iw1p2*)
212212
soc="A31s"
213213
;;
214-
sun7i|Sun8iw2p1)
214+
*sun7i*|*Sun8iw2p1*)
215215
soc="A20"
216216
if [[ $machine == "Banana Pi"* ]]; then
217217
tp="BananaPi"
218218
elif [[ $machine == "Banana Pro"* ]]; then
219219
tp="BananaPro"
220220
fi
221221
;;
222-
sun8i|Sun8iw7p1)
222+
*sun8i*|*Sun8iw7p1*)
223223
soc="H3"
224224
;;
225-
Sun8iw3p1)
225+
*Sun8iw3p1*)
226226
soc="A23"
227227
;;
228-
Sun8iw5p1)
228+
*Sun8iw5p1*)
229229
soc="A33"
230230
;;
231-
Sun8iw6p1)
231+
*Sun8iw6p1*)
232232
soc="A83t"
233233
;;
234-
sun9i|Sun9iw1p1)
234+
*sun9i*|*Sun9iw1p1*)
235235
soc="A80"
236236
;;
237-
Sun9iw1p2)
237+
*Sun9iw1p2*)
238238
soc="A80t"
239239
;;
240-
sun50i|Sun50iw1p1)
240+
*sun50i*|*Sun50iw1p1*)
241241
soc="A64"
242242
;;
243243
'Generic AM33XX'*)

drivers/BCM/BCM.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,21 @@ BCMClass::~BCMClass()
3434
}
3535
}
3636

37+
uint8_t BCMClass::init()
38+
{
39+
if (!bcm2835_init()) {
40+
logError("Failed to initialized bcm2835.\n");
41+
exit(1);
42+
}
43+
initialized = 1;
44+
45+
return 1;
46+
}
47+
3748
void BCMClass::pinMode(uint8_t gpio, uint8_t mode)
3849
{
3950
if (!initialized) {
40-
if (!bcm2835_init()) {
41-
logError("Failed to initialized bcm2835.\n");
42-
exit(1);
43-
}
44-
initialized = 1;
51+
init();
4552
}
4653

4754
bcm2835_gpio_fsel(gpio, mode);
@@ -50,11 +57,7 @@ void BCMClass::pinMode(uint8_t gpio, uint8_t mode)
5057
void BCMClass::digitalWrite(uint8_t gpio, uint8_t value)
5158
{
5259
if (!initialized) {
53-
if (!bcm2835_init()) {
54-
logError("Failed to initialized bcm2835.\n");
55-
exit(1);
56-
}
57-
initialized = 1;
60+
init();
5861
}
5962

6063
bcm2835_gpio_write(gpio, value);
@@ -65,12 +68,13 @@ void BCMClass::digitalWrite(uint8_t gpio, uint8_t value)
6568
uint8_t BCMClass::digitalRead(uint8_t gpio)
6669
{
6770
if (!initialized) {
68-
if (!bcm2835_init()) {
69-
logError("Failed to initialized bcm2835.\n");
70-
exit(1);
71-
}
72-
initialized = 1;
71+
init();
7372
}
7473

7574
return bcm2835_gpio_lev(gpio);
7675
}
76+
77+
uint8_t BCMClass::isInitialized()
78+
{
79+
return initialized;
80+
}

drivers/BCM/BCM.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ class BCMClass
3737
* @brief BCMClass destructor.
3838
*/
3939
~BCMClass();
40+
/**
41+
* @brief Initializes BCM.
42+
*
43+
* @return 1 if successful, else exits the program.
44+
*/
45+
uint8_t init();
4046
/**
4147
* @brief Configures the specified pin to behave either as an input or an output.
4248
*
@@ -65,6 +71,12 @@ class BCMClass
6571
* @return The GPIO pin number.
6672
*/
6773
inline uint8_t digitalPinToInterrupt(uint8_t gpio);
74+
/**
75+
* @brief Checks if SPI was initialized.
76+
*
77+
* @return 1 if initialized, else 0.
78+
*/
79+
uint8_t isInitialized();
6880

6981
private:
7082
static uint8_t initialized; //!< @brief BCM initialized flag.

drivers/BCM/SPIBCM.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ uint8_t SPIBCMClass::initialized = 0;
3434
void SPIBCMClass::begin()
3535
{
3636
if (!initialized) {
37+
if (!BCM.isInitialized()) {
38+
BCM.init();
39+
}
3740
if (!bcm2835_spi_begin()) {
3841
logError("You need root privilege to use SPI.\n");
3942
exit(1);

drivers/Linux/SPIDEV.cpp

Lines changed: 102 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ SPIDEVClass SPIDEV = SPIDEVClass();
3737
uint8_t SPIDEVClass::initialized = 0;
3838
int SPIDEVClass::fd = -1;
3939
std::string SPIDEVClass::device = SPI_SPIDEV_DEVICE;
40+
uint8_t SPIDEVClass::mode = SPI_MODE0;
4041
uint32_t SPIDEVClass::speed = SPI_CLOCK_BASE;
41-
uint32_t SPIDEVClass::speed_temp = SPI_CLOCK_BASE;
42-
struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,1,0,0,0}; // 8 bits_per_word, 1 cs_change
42+
uint8_t SPIDEVClass::bit_order = MSBFIRST;
43+
struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,0,0,0,0}; // 8 bits_per_word, 0 cs_change
4344

4445
SPIDEVClass::SPIDEVClass()
4546
{
@@ -78,15 +79,21 @@ void SPIDEVClass::end()
7879
}
7980
}
8081

81-
void SPIDEVClass::setBitOrder(uint8_t bit_order)
82+
void SPIDEVClass::setBitOrder(uint8_t border)
8283
{
8384
pthread_mutex_lock(&spiMutex);
8485

8586
/*
8687
* bit order
8788
*/
88-
int lsb_setting = bit_order;
89-
int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
89+
bit_order = border;
90+
int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
91+
if (ret == -1) {
92+
logError("Can't set SPI bit order.\n");
93+
abort();
94+
}
95+
96+
ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
9097
if (ret == -1) {
9198
logError("Can't set SPI bit order.\n");
9299
abort();
@@ -102,7 +109,14 @@ void SPIDEVClass::setDataMode(uint8_t data_mode)
102109
/*
103110
* spi mode
104111
*/
105-
int ret = ioctl(fd, SPI_IOC_WR_MODE, &data_mode);
112+
mode = data_mode;
113+
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
114+
if (ret == -1) {
115+
logError("Can't set SPI mode.\n");
116+
abort();
117+
}
118+
119+
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
106120
if (ret == -1) {
107121
logError("Can't set SPI mode.\n");
108122
abort();
@@ -113,6 +127,10 @@ void SPIDEVClass::setDataMode(uint8_t data_mode)
113127

114128
void SPIDEVClass::setClockDivider(uint16_t divider)
115129
{
130+
if (divider == 0) {
131+
return;
132+
}
133+
116134
pthread_mutex_lock(&spiMutex);
117135

118136
/*
@@ -125,6 +143,12 @@ void SPIDEVClass::setClockDivider(uint16_t divider)
125143
abort();
126144
}
127145

146+
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
147+
if (ret == -1) {
148+
logError("Can't set SPI max speed hz.\n");
149+
abort();
150+
}
151+
128152
pthread_mutex_unlock(&spiMutex);
129153
}
130154

@@ -195,29 +219,63 @@ void SPIDEVClass::beginTransaction(SPISettings settings)
195219
/*
196220
* spi mode
197221
*/
198-
ret = ioctl(fd, SPI_IOC_WR_MODE, &settings.dmode);
199-
if (ret == -1) {
200-
logError("Can't set spi mode.\n");
201-
abort();
222+
if (settings.dmode != mode) {
223+
mode = settings.dmode;
224+
225+
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
226+
if (ret == -1) {
227+
logError("Can't set spi mode.\n");
228+
abort();
229+
}
230+
231+
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
232+
if (ret == -1) {
233+
logError("Can't set spi mode.\n");
234+
abort();
235+
}
202236
}
203237

204-
// Save the current speed
205-
speed_temp = speed;
206-
speed = settings.clock;
238+
/*
239+
* speed
240+
*/
241+
if (settings.clock != speed) {
242+
speed = settings.clock;
243+
244+
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
245+
if (ret == -1) {
246+
logError("Can't set SPI max speed hz.\n");
247+
abort();
248+
}
249+
250+
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
251+
if (ret == -1) {
252+
logError("Can't set SPI max speed hz.\n");
253+
abort();
254+
}
255+
}
207256

208257
/*
209258
* bit order
210259
*/
211-
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &settings.border);
212-
if (ret == -1) {
213-
logError("Can't set bits per word.\n");
214-
abort();
260+
if (settings.border != bit_order) {
261+
bit_order = settings.border;
262+
263+
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
264+
if (ret == -1) {
265+
logError("Can't set SPI bit order.\n");
266+
abort();
267+
}
268+
269+
ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
270+
if (ret == -1) {
271+
logError("Can't set SPI bit order.\n");
272+
abort();
273+
}
215274
}
216275
}
217276

218277
void SPIDEVClass::endTransaction()
219278
{
220-
speed = speed_temp;
221279
pthread_mutex_unlock(&spiMutex);
222280
}
223281

@@ -248,38 +306,59 @@ void SPIDEVClass::init()
248306
/*
249307
* spi mode
250308
*/
251-
uint8_t mode = SPI_MODE0;
252309
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
253310
if (ret == -1) {
254311
logError("Can't set SPI mode.\n");
255312
abort();
256313
}
257314

315+
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
316+
if (ret == -1) {
317+
logError("Can't set SPI mode.\n");
318+
abort();
319+
}
320+
258321
/*
259322
* bits per word
260323
*/
261-
uint8_t bits = 0; // 0 corresponds to 8 bits per word
324+
uint8_t bits = 8; // 8 bits per word
262325
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
263326
if (ret == -1) {
264327
logError("Can't set SPI bits per word.\n");
265328
abort();
266329
}
267330

331+
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
332+
if (ret == -1) {
333+
logError("Can't set SPI bits per word.\n");
334+
abort();
335+
}
336+
268337
/*
269338
* max speed hz
270339
*/
271-
speed = SPI_CLOCK_BASE;
272340
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
273341
if (ret == -1) {
274342
logError("Can't set SPI max speed hz.\n");
275343
abort();
276344
}
277345

346+
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
347+
if (ret == -1) {
348+
logError("Can't set SPI max speed hz.\n");
349+
abort();
350+
}
351+
278352
/*
279353
* bit order
280354
*/
281-
int lsb_setting = MSBFIRST;
282-
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
355+
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
356+
if (ret == -1) {
357+
logError("Can't set SPI bit order.\n");
358+
abort();
359+
}
360+
361+
ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
283362
if (ret == -1) {
284363
logError("Can't set SPI bit order.\n");
285364
abort();

drivers/Linux/SPIDEV.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,9 @@ class SPIDEVClass
199199
static uint8_t initialized; //!< @brief SPI initialized flag.
200200
static int fd; //!< @brief SPI device file descriptor.
201201
static std::string device; //!< @brief Default SPI device.
202+
static uint8_t mode; //!< @brief SPI mode.
202203
static uint32_t speed; //!< @brief SPI speed.
203-
static uint32_t speed_temp; //!< @brief Used when doing transaction.
204+
static uint8_t bit_order; //!< @brief SPI bit order.
204205
static struct spi_ioc_transfer tr; //!< @brief Auxiliar struct for data transfer.
205206

206207
static void init();

0 commit comments

Comments
 (0)