-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Migration to busDevice infrastructure: acc/gyro/mag/osd #2290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
This is going to be a big PR 🤔 |
|
|
||
| spiSetSpeed(MPU6000_SPI_INSTANCE, SPI_CLOCK_INITIALIZATON); | ||
|
|
||
| if (!mpu6000InitDone) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't like these initialisation guards. It implies we have lost control of the initialisation sequence. mpu6000AccAndGyroInit should be called once and once only - that renders the guard unnecessary.
Also, as an aside, none of the gyro drivers should have any static data - all required data should be in the gyroDev_t structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, I'm going to remove it eventually. This is merely a proof of concept code.
src/main/drivers/accgyro/accgyro.h
Outdated
| sensorGyroUpdateFuncPtr updateFn; | ||
| extiCallbackRec_t exti; | ||
| busDevice_t bus; | ||
| busDevice_t * dev; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a pointer? And why have you renamed it to dev - that is just confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because busDevice_t object may be shared between gyro and acc (and compass).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it can be shared. But it is small and not often shared. I think it is better to duplicate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinbudden the reason to share the object is that we do device detection (and most of the configuration) only in gyro driver. Acc driver needs to know if gyro device was detected and initialized - shared scratchpad field of the busDevice_t is used for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way this is currently handled is:
- acc init occurs after gyro init
- acc init copies gyro busDevice_t data.
It's straightforward, has and no potential null pointer errors. Note also this works for dual gyro systems in Betaflight.
Sometimes a pragmatic approach is better than a "pure" approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I never likes the part of initialization that was copying around data between gyro_t and acc_t. High-level code needs to know nothing about how devices operate. All hardware sharing issues should be solved at low level.
High-level code needs to do two things: 1) call accWhateverDetect() and 2) call acc->init() on detected device.
If we were sticking to pragmatic approach - we would still be flying Baseflight code 😄
|
|
||
| if (!mpu6000InitDone) { | ||
| // Device Reset | ||
| busWrite(gyro->dev, MPU_RA_PWR_MGMT_1, BIT_H_RESET); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be busWrite(&gyro->bus,...) see earlier comment. busWrite writes to a bus, not to a dev.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then I'll need to refactor this. It's actually writing to a specific dev on the bus.
src/main/drivers/bus.c
Outdated
|
|
||
| #define BUSDEV_MAX_DEVICES 8 | ||
|
|
||
| static busDevice_t busDevPool[BUSDEV_MAX_DEVICES]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So you are adding dynamic allocation of busDevices. Why? It complicates things and is a potential source of error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need a busDevice for each active sensor. Initially I did allocate a static busDevice_t object for each supported sensor, but that was a waste of memory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does waste a bit of memory. But busDevice_t is fairly small, and it's not like we have hundreds of sensors. I'm prepared to pay a bit of RAM for increased reliability.
Also, you statically allocate for 8 sensors anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'll look into reverting back to static allocation.
| void mpuIntExtiInit(gyroDev_t *gyro) | ||
| { | ||
| if (!gyro->mpuIntExtiConfig) { | ||
| if (!gyro->dev->irqPin) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not clear to me that the irqPin should be part of the busDevice_t structure. I think it should probably be part of the gyroDev_t structure.
| uint8_t address; // I2C bus device address | ||
| } i2c; | ||
| } busdev; | ||
| IO_t irqPin; // Device IRQ pin. Bus system will only assign IO_t object to this var. Initialization is up to device driver |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the device driver should probably own the irqPin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an abstraction of a generic device on a bus. Most devices have an IRQ pin. We might not use it, but we have it. Allocating and handling it in one place is more logical than to allow each of the drivers handle it on it's own.
I'm even thinking about handling incoming interrupts in the busDevice_t layer in driver-independent maner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it's not handled in one place. Your comment specifically says Bus system will only assign IO_t object to this var. Initialization is up to device driver
As a general rule of thumb, the thing that does the initialisation should have ownership (I agree there are sometimes exceptions).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martinbudden that's temporary. The code is far from completion. Eventually IRQ handling code will be migrated to busDevice_t and only callbacks & flags will be exposed to device driver.
|
See some specific comments in the code. However my biggest issue with this is the dynamic allocation of buses. Dynamic allocation adds the potential for errors. What are the advantages that you seek? |
I'm not sure about that. The gyro device should not need to know that it shares a bus with the acc device or vice versa. It's actually the higher level code that knows the two devices are packaged into one chip. Everything should be as simple as possible. An accelerometer device driver that doesn't know anything about a gyro is simpler than one that does know. Of course somebody needs to know, but I argue that knowledge is correctly placed in the sensor code, not the device driver code. The pragmatic bit I am talking about is the copying of data rather than using pointers. However, whether the bus is copied or whether a pointer is used, the knowledge still belongs in the sensor layer. |
|
The |
9cbe712 to
a4d9d5f
Compare
a4d9d5f to
23e8dee
Compare
|
I'm thinking about separating drivers for native AK8963 over I2C and AK8963 built-in into MPU9250. What we have currently: What I intend to do: Thoughs? |
2d82dfb to
1477eeb
Compare
|
Testing of this PR is needed on as much targets as possible. Shouldn't affect flight performance, only sensor detection and reading. Some targets (ones having MPU9250) will likely require changing the accelerometer type. |
|
I flashed this on my F3 OMNIBUS. The baro (BMP280) is no longer detected. Going back to development or de_agl_estimation and it's OK again: de_busdev_migration de_agl_estimation I said I would test de_agl_estimation tomorrow anyway, so that settles it. |
|
This is odd. BMP280 is on SPI bus which didn't change. I'll verify on my OMNIBUS F3 board. |
|
@stronnag bug confirmed. Working on a fix |
|
Bug fixed. Caused by incorrect hw definition for BMP085/BMP180 which was overriding BMP280 |
|
Should be functional on OMNIBUS and other targets now |
|
Just flashed an SPRACINGF3EVO, after |
|
flight tested on Omnibus F3 and SPRacingF3Evo, locally merged with development. Nav modes (WP, RTH, PH, turn off TX failsafe RTH, free flight). |
|
Tested on Matek F405, locally merged with development. Nav modes (WP, RTH, PH, free flight). So back to the SPRF3, which was marked as 'flown' rather than 'tested', for a reason. Yesterday (genuine SPRF3 board) I was not content, often it would not arm without multiple power cycles and when it did arm, horizon mode appeared to lose its idea of level. Today I tried a Dodo board (same firmware), when it wouldn't arm I plugged in mwp to see 'Not level' reported (when it obviously was) -- and the AH indicating inverted. Flashed back to development, which was perfectly OK. So there appears to be an ACC initialisation / stability issue on SPRF3. Final assessment: Omnibus, SPRF3EVO, Matek F405: Content, no regression |
|
Ok. Thanks for testing @stronnag. I'll debug once I get home. I believe we have an issue with MPU6050 driver (most likely the 6050 revision detection code). |
|
@stronnag strangely I can't reproduce on either of my two SPRacingF3 boards. Can you do a flash with full erase and check the values of Accelerometer in Sensors tab? |
|
The two SPRF3 seem OK after a reflash. Apologies for the diversion. |
|
No worries @stronnag. There must be a place in gyroConfig which changed and should be reset. I'll find and fix it to make sure config is consistent. |
|
Ok, I believe this can be merged now. This PR is already very big - I'll improve the code in next PRs. |
d55af2a to
0a28733
Compare
0a28733 to
8d9f68c
Compare
|
It would help immeasurably if you could tell us which FC, which version of iNav and provide a CLI diff. And if it's not 1.9-RC1, please try that. |
Refactoring of busDevice code, migration of a acc/gyro sensors to busDevice