-
Notifications
You must be signed in to change notification settings - Fork 7.1k
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
drivers: sensor: add bosch bmm350 driver #85174
drivers: sensor: add bosch bmm350 driver #85174
Conversation
984e072
to
7f86bca
Compare
7f86bca
to
e809e15
Compare
@@ -0,0 +1,8 @@ | |||
# Copyright (c) 2024 Bosch Sensortec GmbH |
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.
Update the copyright year
# Copyright (c) 2024 Bosch Sensortec GmbH | |
# Copyright (c) 2025 Bosch Sensortec GmbH |
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'm not working for Bosch, I'm just integrating their code. Not sure if that's something I'm allowed to do.
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.
What do you mean with "their code", if you copied code then you should adhere to the original code's copyright. Otherwise if you produced this code, you shouldn't be putting Bosch's copyright, but your own.
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.
Bosch wrote this code, including the copyright headers and sent it to me. I was told it's okay to share, so I'm doing that here.
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 guess this is OK? @carlescufi
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.
Bosch needs to clarify this directly I guess.
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.
@kegov Could you confirm?
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.
@maxd-nordic & @gmarull , I confirm.
e809e15
to
ae8ec0b
Compare
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.
this PR contains many portions copied from https://github.com/boschsensortec/BMM350_SensorAPI, which is BSD-3 licensed. Unless Bosch explicitly says they are happy to share this code as Apache-2.0, this PR can't go in.
drivers/sensor/bosch/bmm350/bmm350.c
Outdated
BMM350_GET_BITS(rx_buf[2], BMM350_PMU_CMD_VALUE); | ||
} | ||
} else { | ||
ret = BMM350_E_NULL_PTR; |
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.
-1 on custom error handling schemes here, this is copy&paste from their "hal"
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.
Is this a blocker?
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
samples/sensor/bmm350/src/main.c
Outdated
report_mag[0] = mag[0].val1 + mag[0].val2 / 100.0; | ||
report_mag[1] = mag[1].val1 + mag[1].val2 / 100.0; | ||
report_mag[2] = mag[2].val1 + mag[2].val2 / 100.0; |
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.
something's wrong if you can't use sensor_value_to_double/float
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'll fix the order of magnitude here
samples/sensor/bmm350/src/main.c
Outdated
/* Setting scale in G, due to loss of precision if the SI unit m/s^2 | ||
* is used | ||
*/ | ||
sampling_freq.val1 = 25; /* Hz from 0.78 to 400*/ | ||
sampling_freq.val2 = 0; /*not use*/ | ||
oversampling.val1 = 1; /*1 Normal mode 0suspend mode*/ | ||
oversampling.val2 = 0; /*not use*/ | ||
sensor_attr_set(dev, SENSOR_CHAN_MAGN_XYZ, | ||
SENSOR_ATTR_SAMPLING_FREQUENCY, | ||
&sampling_freq); | ||
/* Set sampling frequency last as this also sets the appropriate | ||
* power mode. If already sampling, change to 0.0Hz before changing | ||
* other attributes | ||
*/ | ||
sensor_attr_set(dev, SENSOR_CHAN_MAGN_XYZ, SENSOR_ATTR_OVERSAMPLING, | ||
&oversampling); |
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.
doing pseudo-power management here?
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.
which change would you like me to do here?
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.
how does oversampling relate to "1 Normal mode 0suspend mode", this looks wrong
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.
This is just odd naming. It does match the chip's datasheet though. The driver only supports "normal mode" and "suspend mode", but you could theoretically put other values in the register.
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.
This still looks very wrong, this chip does support oversampling mode, I gave comments in other area, that it should be able to be configured
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.
you can configure oversampling with this. there is just a special check for the value "0", that turns the chip into low power mode. What change do I need to make here?
It was Bosch who gave me these files with the Apache-2.0 headers. |
ae8ec0b
to
a7d3868
Compare
Hey folks! Thanks for the reviews! Please have another look. I think I caught all of the change requests. |
f98c10a
to
71d6a76
Compare
} | ||
static uint8_t acc_odr_to_reg(const struct sensor_value *val) | ||
{ | ||
double odr = sensor_value_to_double((struct sensor_value *)val); |
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.
Do you have to use double
here? This could bring in a lot of code and cause some overhead for FPU-less processors
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.
Please don't make me rework this whole driver. Other Bosch drivers that are already part of Zephyr do the same.
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.
A later PR can change this behavior for all drivers that have it.
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'm not sure why you need to rework this whole driver? You can easily do this with UQ27.5 fixed point format... might as well start somewhere with not using doubles then
static uint8_t acc_odr_to_reg(const struct sensor_value *val)
{
/* Convert sensor_value to fixed-point UQ27.5 format */
uint32_t fixed_odr = (val->val1 << 5) + (((uint64_t)val->val2 * 32) / 1000000);
uint8_t reg = BMM350_DATA_RATE_100HZ;
if ((fixed_odr >= 25) && (fixed_odr <= 50)) {
/* 0.78125Hz to 1.5625Hz */
reg = BMM350_DATA_RATE_1_5625HZ;
} else if ((fixed_odr > 50) && (fixed_odr <= 100)) {
/* 1.5625Hz to 3.125Hz */
reg = BMM350_DATA_RATE_3_125HZ;
} else if ((fixed_odr > 100) && (fixed_odr <= 200)) {
/* 3.125Hz to 6.25Hz */
reg = BMM350_DATA_RATE_6_25HZ;
} else if ((fixed_odr > 200) && (fixed_odr <= 400)) {
/* 6.25Hz to 12.5Hz */
reg = BMM350_DATA_RATE_12_5HZ;
} else if ((fixed_odr > 800) && (fixed_odr <= 1600)) {
/* 12.5Hz to 25Hz */
reg = BMM350_DATA_RATE_25HZ;
} else if ((fixed_odr > 1600) && (fixed_odr <= 3200)) {
/* 25Hz to 50Hz */
reg = BMM350_DATA_RATE_50HZ;
} else if ((fixed_odr > 3200) && (fixed_odr <= 6400)) {
/* 50Hz to 100Hz */
reg = BMM350_DATA_RATE_100HZ;
} else if ((fixed_odr > 6400) && (fixed_odr <= 12800)) {
/* 100Hz to 200Hz */
reg = BMM350_DATA_RATE_200HZ;
} else if ((fixed_odr > 12800) && (fixed_odr <= 25600)) {
/* 200Hz to 400Hz */
reg = BMM350_DATA_RATE_400HZ;
} else if (fixed_odr > 25600) {
/* 400Hz */
reg = BMM350_DATA_RATE_400HZ;
}
return reg;
}
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.
actually, on second thought, there are a few different ways to approach this such as with sensor_value_to_micro
... but I have to agree with @teburd in another comment about this fuzzy approach, I'm reverting my block on this now
drivers/sensor/bosch/bmm350/bmm350.c
Outdated
if ((odr == BMM350_DATA_RATE_400HZ) && (performance >= BMM350_AVERAGING_2)) { | ||
performance_fix = BMM350_NO_AVERAGING; | ||
} else if ((odr == BMM350_DATA_RATE_200HZ) && (performance >= BMM350_AVERAGING_4)) { | ||
performance_fix = BMM350_AVERAGING_2; | ||
} else if ((odr == BMM350_DATA_RATE_100HZ) && (performance >= BMM350_AVERAGING_8)) { | ||
performance_fix = BMM350_AVERAGING_4; | ||
} |
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.
suggestion: it may be good to print a LOG_WRN about how it's adjusting the oversampling rate from what the application tried to specify
drivers/sensor/bosch/bmm350/Kconfig
Outdated
thread_stack_size = 1024 | ||
source "drivers/sensor/Kconfig.trigger_template" | ||
|
||
config BMM350_SAMPLING_RATE_RUNTIME |
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 can't see where this is used
drivers/sensor/bosch/bmm350/Kconfig
Outdated
config BMM350_THREAD_PRIORITY | ||
int "Own thread priority" | ||
depends on BMM350_TRIGGER_OWN_THREAD | ||
default 10 | ||
help | ||
Priority of the thread used by the driver to handle interrupts. | ||
|
||
config BMM350_THREAD_STACK_SIZE | ||
int "Own thread stack size" | ||
depends on BMM350_TRIGGER_OWN_THREAD | ||
default 1024 | ||
help | ||
Stack size of thread used by the driver to handle interrupts. |
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.
These look like they are defined twice as they are already defined with the Kconfig.trigger_template
drivers/sensor/bosch/bmm350/bmm350.c
Outdated
reg = BMM350_AVERAGING_8; | ||
break; | ||
default: | ||
LOG_ERR("unsupported oversampling rate"); |
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.
shouldn't this return a status code (-EINVAL
) and not set to a 'default' value if a wrong value is tried, then of course bubble up the error code
7c4e77a
to
afa35aa
Compare
will let sensor maintainers/collaborators finish the review |
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.
Please, no part specific samples. Either make the sample generic for the task or add overlays to existing samples (magn_polling/magn_trig) for the board+part you want to use.
|
||
uint8_t reg = BMM350_DATA_RATE_100HZ; | ||
|
||
if ((odr >= 0.78125) && (odr <= 1.5625)) { |
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 love these fuzzy ODR setters, but I know there's precedence in the tree for them.
What's weird about this idea is that you can set arbitrary ODRs and from the API response and call it may seem as if any ODR is possible because hey, it didn't fail!
The reality is the actual ODR is set to something else entirely... and unless you go read this attribute back you don't know.
Maybe ODR should be something we do more explicitly rather than with attributes. It's incredibly common, typically gets tied to some sample power mode (toggled/always on are common...) and really should give back the ODR in use rather than simply accepting any ODR and replying back with "Ok!"
TL;DR no changes required but I don't love this
return rslt; | ||
} | ||
|
||
static int bmm350_sample_fetch(const struct device *dev, enum sensor_channel chan) |
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.
What happens if the sensor is suspended through PM API? We don't have a solid answer for this today with the fetch+get API other than the application doing the power management reference counting on the sensors. But if the device is suspended and this is called, what happens?
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.
All registers are available in suspend mode. They will not update when no measurements are run. Do you need this to be changed?
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.
No, but this might be surprising behavior to a caller, maybe worth a warning log if CONFIG_DEBUG or something is toggled?
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 this behaves as it should with the PM model.
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 doesn't make sense to me to clutter the driver with this. Other drivers will also just try to fetch, no matter if the power mode allows for it.
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 will the registers continue to hold a reading from some past moment in time then or be all zeros?
afa35aa
to
75c6726
Compare
Add driver for Bosch BMM350 magnetometer sensor. Signed-off-by: Maximilian Deubel <maximilian.deubel@nordicsemi.no>
75c6726
to
cc9f68d
Compare
@teburd @XenuIsWatching @yperess Could you please unblock this PR? |
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.
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 changed my mind after think it about it more on the last comment,
lgtm now
No blocking issues left, though I think some things need to be clarified in how sensor drivers should be written.
Agreed to @MaureenHelm to add @teburd and @yperess as assignees as she is on vacation this week |
upstream Bosch's BMM350 driver.
this is necessary for the thingy91x.