Skip to content

Commit 7134c41

Browse files
imu: improve interrupt-safety of CurieImu API methods
Ensure that SPI transfers cannot be interrupted, and avoid use of global buffer to improve interrupt safety Signed-off-by: Dan O'Donovan <dan@emutex.com>
1 parent 252bd53 commit 7134c41

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

libraries/CurieImu/src/BMI160.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,15 @@ THE SOFTWARE.
4444

4545
uint8_t BMI160Class::reg_read (uint8_t reg)
4646
{
47+
uint8_t buffer[1];
4748
buffer[0] = reg;
4849
serial_buffer_transfer(buffer, 1, 1);
4950
return buffer[0];
5051
}
5152

5253
void BMI160Class::reg_write(uint8_t reg, uint8_t data)
5354
{
55+
uint8_t buffer[2];
5456
buffer[0] = reg;
5557
buffer[1] = data;
5658
serial_buffer_transfer(buffer, 2, 0);
@@ -890,6 +892,7 @@ void BMI160Class::setStepCountEnabled(bool enabled) {
890892
* @see BMI160_RA_STEP_CNT_L
891893
*/
892894
uint16_t BMI160Class::getStepCount() {
895+
uint8_t buffer[2];
893896
buffer[0] = BMI160_RA_STEP_CNT_L;
894897
serial_buffer_transfer(buffer, 1, 2);
895898
return (((uint16_t)buffer[1]) << 8) | buffer[0];
@@ -1535,6 +1538,7 @@ void BMI160Class::setGyroFIFOEnabled(bool enabled) {
15351538
* @see BMI160_RA_FIFO_LENGTH_0
15361539
*/
15371540
uint16_t BMI160Class::getFIFOCount() {
1541+
uint8_t buffer[2];
15381542
buffer[0] = BMI160_RA_FIFO_LENGTH_0;
15391543
serial_buffer_transfer(buffer, 1, 2);
15401544
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2156,6 +2160,7 @@ void BMI160Class::setIntEnabled(bool enabled) {
21562160
* @see BMI160_RA_GYRO_X_L
21572161
*/
21582162
void BMI160Class::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz) {
2163+
uint8_t buffer[12];
21592164
buffer[0] = BMI160_RA_GYRO_X_L;
21602165
serial_buffer_transfer(buffer, 1, 12);
21612166
*gx = (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2203,6 +2208,7 @@ void BMI160Class::getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx,
22032208
* @see BMI160_RA_ACCEL_X_L
22042209
*/
22052210
void BMI160Class::getAcceleration(int16_t* x, int16_t* y, int16_t* z) {
2211+
uint8_t buffer[6];
22062212
buffer[0] = BMI160_RA_ACCEL_X_L;
22072213
serial_buffer_transfer(buffer, 1, 6);
22082214
*x = (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2216,6 +2222,7 @@ void BMI160Class::getAcceleration(int16_t* x, int16_t* y, int16_t* z) {
22162222
* @see BMI160_RA_ACCEL_X_L
22172223
*/
22182224
int16_t BMI160Class::getAccelerationX() {
2225+
uint8_t buffer[2];
22192226
buffer[0] = BMI160_RA_ACCEL_X_L;
22202227
serial_buffer_transfer(buffer, 1, 2);
22212228
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2227,6 +2234,7 @@ int16_t BMI160Class::getAccelerationX() {
22272234
* @see BMI160_RA_ACCEL_Y_L
22282235
*/
22292236
int16_t BMI160Class::getAccelerationY() {
2237+
uint8_t buffer[2];
22302238
buffer[0] = BMI160_RA_ACCEL_Y_L;
22312239
serial_buffer_transfer(buffer, 1, 2);
22322240
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2238,6 +2246,7 @@ int16_t BMI160Class::getAccelerationY() {
22382246
* @see BMI160_RA_ACCEL_Z_L
22392247
*/
22402248
int16_t BMI160Class::getAccelerationZ() {
2249+
uint8_t buffer[2];
22412250
buffer[0] = BMI160_RA_ACCEL_Z_L;
22422251
serial_buffer_transfer(buffer, 1, 2);
22432252
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2261,6 +2270,7 @@ int16_t BMI160Class::getAccelerationZ() {
22612270
* @see BMI160_RA_TEMP_L
22622271
*/
22632272
int16_t BMI160Class::getTemperature() {
2273+
uint8_t buffer[2];
22642274
buffer[0] = BMI160_RA_TEMP_L;
22652275
serial_buffer_transfer(buffer, 1, 2);
22662276
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2300,6 +2310,7 @@ int16_t BMI160Class::getTemperature() {
23002310
* @see BMI160_RA_GYRO_X_L
23012311
*/
23022312
void BMI160Class::getRotation(int16_t* x, int16_t* y, int16_t* z) {
2313+
uint8_t buffer[6];
23032314
buffer[0] = BMI160_RA_GYRO_X_L;
23042315
serial_buffer_transfer(buffer, 1, 6);
23052316
*x = (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2313,6 +2324,7 @@ void BMI160Class::getRotation(int16_t* x, int16_t* y, int16_t* z) {
23132324
* @see BMI160_RA_GYRO_X_L
23142325
*/
23152326
int16_t BMI160Class::getRotationX() {
2327+
uint8_t buffer[2];
23162328
buffer[0] = BMI160_RA_GYRO_X_L;
23172329
serial_buffer_transfer(buffer, 1, 2);
23182330
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2324,6 +2336,7 @@ int16_t BMI160Class::getRotationX() {
23242336
* @see BMI160_RA_GYRO_Y_L
23252337
*/
23262338
int16_t BMI160Class::getRotationY() {
2339+
uint8_t buffer[2];
23272340
buffer[0] = BMI160_RA_GYRO_Y_L;
23282341
serial_buffer_transfer(buffer, 1, 2);
23292342
return (((int16_t)buffer[1]) << 8) | buffer[0];
@@ -2335,6 +2348,7 @@ int16_t BMI160Class::getRotationY() {
23352348
* @see BMI160_RA_GYRO_Z_L
23362349
*/
23372350
int16_t BMI160Class::getRotationZ() {
2351+
uint8_t buffer[2];
23382352
buffer[0] = BMI160_RA_GYRO_Z_L;
23392353
serial_buffer_transfer(buffer, 1, 2);
23402354
return (((int16_t)buffer[1]) << 8) | buffer[0];

libraries/CurieImu/src/BMI160.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -583,8 +583,6 @@ class BMI160Class {
583583
void reg_write(uint8_t reg, uint8_t data);
584584
void reg_write_bits(uint8_t reg, uint8_t data, unsigned pos, unsigned len);
585585
uint8_t reg_read_bits(uint8_t reg, unsigned pos, unsigned len);
586-
587-
uint8_t buffer[12];
588586
};
589587

590588
#endif /* _BMI160_H_ */

libraries/CurieImu/src/CurieImu.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "CurieImu.h"
2121
#include "internal/ss_spi.h"
22+
#include "interrupt.h"
2223

2324
#define BMI160_GPIN_AON_PIN 4
2425

@@ -54,10 +55,20 @@ void CurieImuClass::initialize()
5455
*/
5556
int CurieImuClass::serial_buffer_transfer(uint8_t *buf, unsigned tx_cnt, unsigned rx_cnt)
5657
{
58+
int flags, status;
59+
5760
if (rx_cnt) /* For read transfers, assume 1st byte contains register address */
5861
buf[0] |= (1 << BMI160_SPI_READ_BIT);
5962

60-
return ss_spi_xfer(buf, tx_cnt, rx_cnt);
63+
/* Lock interrupts here to
64+
* - avoid concurrent access to the SPI bus
65+
* - avoid delays in SPI transfer due to unrelated interrupts
66+
*/
67+
flags = interrupt_lock();
68+
status = ss_spi_xfer(buf, tx_cnt, rx_cnt);
69+
interrupt_unlock(flags);
70+
71+
return status;
6172
}
6273

6374
/** Interrupt handler for interrupts from PIN1 on the BMI160

0 commit comments

Comments
 (0)