Merge branch 'dev'
Some checks failed
Some checks failed
This commit is contained in:
85
README.md
85
README.md
@ -1,51 +1,7 @@
|
||||
# Zephyr Example Application
|
||||
|
||||
<a href="https://zephyrproject-rtos.github.io/example-application">
|
||||
<img alt="Documentation" src="https://img.shields.io/badge/documentation-3D578C?logo=sphinx&logoColor=white">
|
||||
</a>
|
||||
<a href="https://zephyrproject-rtos.github.io/example-application/doxygen">
|
||||
<img alt="API Documentation" src="https://img.shields.io/badge/API-documentation-3D578C?logo=c&logoColor=white">
|
||||
</a>
|
||||
|
||||
This repository contains a Zephyr example application. The main purpose of this
|
||||
repository is to serve as a reference on how to structure Zephyr-based
|
||||
applications. Some of the features demonstrated in this example are:
|
||||
|
||||
- Basic [Zephyr application][app_dev] skeleton
|
||||
- [Zephyr workspace applications][workspace_app]
|
||||
- [Zephyr modules][modules]
|
||||
- [West T2 topology][west_t2]
|
||||
- [Custom boards][board_porting]
|
||||
- Custom [devicetree bindings][bindings]
|
||||
- Out-of-tree [drivers][drivers]
|
||||
- Out-of-tree libraries
|
||||
- Example CI configuration (using Github Actions)
|
||||
- Custom [west extension][west_ext]
|
||||
- Doxygen and Sphinx documentation boilerplate
|
||||
|
||||
This repository is versioned together with the [Zephyr main tree][zephyr]. This
|
||||
means that every time that Zephyr is tagged, this repository is tagged as well
|
||||
with the same version number, and the [manifest](west.yml) entry for `zephyr`
|
||||
will point to the corresponding Zephyr tag. For example, the `example-application`
|
||||
v2.6.0 will point to Zephyr v2.6.0. Note that the `main` branch always
|
||||
points to the development branch of Zephyr, also `main`.
|
||||
|
||||
[app_dev]: https://docs.zephyrproject.org/latest/develop/application/index.html
|
||||
[workspace_app]: https://docs.zephyrproject.org/latest/develop/application/index.html#zephyr-workspace-app
|
||||
[modules]: https://docs.zephyrproject.org/latest/develop/modules.html
|
||||
[west_t2]: https://docs.zephyrproject.org/latest/develop/west/workspaces.html#west-t2
|
||||
[board_porting]: https://docs.zephyrproject.org/latest/guides/porting/board_porting.html
|
||||
[bindings]: https://docs.zephyrproject.org/latest/guides/dts/bindings.html
|
||||
[drivers]: https://docs.zephyrproject.org/latest/reference/drivers/index.html
|
||||
[zephyr]: https://github.com/zephyrproject-rtos/zephyr
|
||||
[west_ext]: https://docs.zephyrproject.org/latest/develop/west/extensions.html
|
||||
|
||||
## Getting Started
|
||||
|
||||
Before getting started, make sure you have a proper Zephyr development
|
||||
environment. Follow the official
|
||||
[Zephyr Getting Started Guide](https://docs.zephyrproject.org/latest/getting_started/index.html).
|
||||
|
||||
### Initialization
|
||||
|
||||
The first step is to initialize the workspace folder (``my-workspace``) where
|
||||
@ -65,21 +21,8 @@ west update
|
||||
To build the application, run the following command:
|
||||
|
||||
```shell
|
||||
cd example-application
|
||||
west build -b $BOARD app
|
||||
```
|
||||
|
||||
where `$BOARD` is the target board.
|
||||
|
||||
You can use the `custom_plank` board found in this
|
||||
repository. Note that Zephyr sample boards may be used if an
|
||||
appropriate overlay is provided (see `app/boards`).
|
||||
|
||||
A sample debug configuration is also provided. To apply it, run the following
|
||||
command:
|
||||
|
||||
```shell
|
||||
west build -b $BOARD app -- -DOVERLAY_CONFIG=debug.conf
|
||||
cd mellifera_firmware
|
||||
west build -b mellifera_rev1 app
|
||||
```
|
||||
|
||||
Once you have built the application, run the following command to flash it:
|
||||
@ -88,6 +31,30 @@ Once you have built the application, run the following command to flash it:
|
||||
west flash
|
||||
```
|
||||
|
||||
```shell
|
||||
go install github.com/apache/mynewt-mcumgr-cli/mcumgr@latest
|
||||
```
|
||||
|
||||
### Bootloader
|
||||
```shell
|
||||
# build and flash the bootloader
|
||||
west build -p -b mellifera_rev1 ../mcuboot/boot/zephyr/ -- -DCONF_FILE=$(pwd)/boot.conf
|
||||
west flash
|
||||
|
||||
# define serial connection to device
|
||||
~/go/bin/mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512"
|
||||
~/go/bin/mcumgr conn add ttyusb0 type="serial" connstring="dev=/dev/ttyUSB0,baud=115200,mtu=512"
|
||||
|
||||
# hold button while power cycling to enter bootloading mode
|
||||
~/go/bin/mcumgr -c usbtty0 image list
|
||||
|
||||
# build the app
|
||||
west build -p -b mellifera_rev1 app
|
||||
|
||||
~/go/bin/mcumgr -c ttyusb0 image upload -e build/zephyr/zephyr.signed.bin
|
||||
~/go/bin/mcumgr -c usbtty0 image list
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
To execute Twister integration tests, run the following command:
|
||||
|
18
app/prj.conf
18
app/prj.conf
@ -5,3 +5,21 @@
|
||||
|
||||
CONFIG_SENSOR=y
|
||||
CONFIG_BLINK=y
|
||||
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=16384
|
||||
|
||||
CONFIG_DISPLAY=y
|
||||
|
||||
CONFIG_LOG=y
|
||||
|
||||
CONFIG_CFB_LOG_LEVEL_DBG=y
|
||||
CONFIG_CHARACTER_FRAMEBUFFER=y
|
||||
CONFIG_CBPRINTF_FP_SUPPORT=y
|
||||
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_DEVICE_NAME="Mellifera"
|
||||
|
||||
CONFIG_BOOTLOADER_MCUBOOT=y
|
||||
CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE=y
|
345
app/src/main.c
345
app/src/main.c
@ -6,77 +6,352 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/display/cfb.h>
|
||||
|
||||
#include <app/drivers/blink.h>
|
||||
|
||||
#include <app_version.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
||||
LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL);
|
||||
|
||||
#define BLINK_PERIOD_MS_STEP 100U
|
||||
#define BLINK_PERIOD_MS_MAX 1000U
|
||||
#define BLINK_PERIOD_MS_MAX 1000U
|
||||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
|
||||
/*
|
||||
* Set Advertisement data. Based on the Eddystone specification:
|
||||
* https://github.com/google/eddystone/blob/master/protocol-specification.md
|
||||
* https://github.com/google/eddystone/tree/master/eddystone-url
|
||||
*/
|
||||
static const struct bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
|
||||
BT_DATA_BYTES(BT_DATA_UUID16_ALL, 0xaa, 0xfe),
|
||||
BT_DATA_BYTES(BT_DATA_SVC_DATA16,
|
||||
0xaa, 0xfe, /* Eddystone UUID */
|
||||
0x10, /* Eddystone-URL frame type */
|
||||
0x00, /* Calibrated Tx power at 0m */
|
||||
0x00, /* URL Scheme Prefix http://www. */
|
||||
'z', 'e', 'p', 'h', 'y', 'r',
|
||||
'p', 'r', 'o', 'j', 'e', 'c', 't',
|
||||
0x08) /* .org */
|
||||
};
|
||||
|
||||
/* Set Scan Response data */
|
||||
static const struct bt_data sd[] = {
|
||||
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
|
||||
};
|
||||
|
||||
static void bt_ready(int err)
|
||||
{
|
||||
char addr_s[BT_ADDR_LE_STR_LEN];
|
||||
bt_addr_le_t addr = {0};
|
||||
size_t count = 1;
|
||||
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Bluetooth init failed (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INF("Bluetooth initialized");
|
||||
|
||||
/* Start advertising */
|
||||
err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad),
|
||||
sd, ARRAY_SIZE(sd));
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Advertising failed to start (err %d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* For connectable advertising you would use
|
||||
* bt_le_oob_get_local(). For non-connectable non-identity
|
||||
* advertising an non-resolvable private address is used;
|
||||
* there is no API to retrieve that.
|
||||
*/
|
||||
|
||||
bt_id_get(&addr, &count);
|
||||
bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));
|
||||
|
||||
LOG_INF("Beacon started, advertising as %s", addr_s);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int ret;
|
||||
unsigned int period_ms = BLINK_PERIOD_MS_MAX;
|
||||
const struct device *sensor, *blink;
|
||||
struct sensor_value last_val = { 0 }, val;
|
||||
const struct device *dev;
|
||||
uint16_t x_res;
|
||||
uint16_t y_res;
|
||||
uint16_t rows;
|
||||
uint8_t ppt;
|
||||
uint8_t font_width;
|
||||
uint8_t font_height;
|
||||
|
||||
printk("Zephyr Example Application %s\n", APP_VERSION_STRING);
|
||||
int err;
|
||||
|
||||
sensor = DEVICE_DT_GET(DT_NODELABEL(example_sensor));
|
||||
if (!device_is_ready(sensor)) {
|
||||
LOG_ERR("Sensor not ready");
|
||||
printk("Starting Mellifera version %s...\n", APP_VERSION_STRING);
|
||||
// printk("Board: %s\n", BOARD);
|
||||
|
||||
LOG_INF("Starting Beacon Demo");
|
||||
|
||||
/* Initialize the Bluetooth Subsystem */
|
||||
err = bt_enable(bt_ready);
|
||||
if (err)
|
||||
{
|
||||
LOG_ERR("Bluetooth init failed (err %d)", err);
|
||||
}
|
||||
|
||||
dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
||||
if (!device_is_ready(dev))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", dev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
blink = DEVICE_DT_GET(DT_NODELABEL(blink_led));
|
||||
if (!device_is_ready(blink)) {
|
||||
LOG_ERR("Blink LED not ready");
|
||||
if (display_set_pixel_format(dev, PIXEL_FORMAT_MONO10) != 0)
|
||||
{
|
||||
if (display_set_pixel_format(dev, PIXEL_FORMAT_MONO01) != 0)
|
||||
{
|
||||
LOG_ERR("Failed to set required pixel format");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INF("Initialized %s", dev->name);
|
||||
|
||||
if (cfb_framebuffer_init(dev))
|
||||
{
|
||||
LOG_ERR("Framebuffer initialization failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = blink_off(blink);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not turn off LED (%d)", ret);
|
||||
cfb_framebuffer_clear(dev, true);
|
||||
|
||||
display_blanking_off(dev);
|
||||
|
||||
x_res = cfb_get_display_parameter(dev, CFB_DISPLAY_WIDTH);
|
||||
y_res = cfb_get_display_parameter(dev, CFB_DISPLAY_HEIGH);
|
||||
rows = cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS);
|
||||
ppt = cfb_get_display_parameter(dev, CFB_DISPLAY_PPT);
|
||||
|
||||
for (int idx = 0; idx < 42; idx++)
|
||||
{
|
||||
if (cfb_get_font_size(dev, idx, &font_width, &font_height))
|
||||
{
|
||||
break;
|
||||
}
|
||||
cfb_framebuffer_set_font(dev, idx);
|
||||
printf("font width %d, font height %d\n",
|
||||
font_width, font_height);
|
||||
}
|
||||
cfb_framebuffer_set_font(dev, 0);
|
||||
|
||||
printf("x_res %d, y_res %d, ppt %d, rows %d, cols %d\n",
|
||||
x_res,
|
||||
y_res,
|
||||
ppt,
|
||||
rows,
|
||||
cfb_get_display_parameter(dev, CFB_DISPLAY_COLS));
|
||||
|
||||
cfb_set_kerning(dev, 3);
|
||||
|
||||
const struct device *ina, *bmp, *bmx, *lis, *hdc;
|
||||
|
||||
ina = DEVICE_DT_GET(DT_NODELABEL(ina231));
|
||||
if (!device_is_ready(ina))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", ina->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
blink_set_period_ms(blink, BLINK_PERIOD_MS_MAX);
|
||||
bmp = DEVICE_DT_GET(DT_NODELABEL(bmp388));
|
||||
if (!device_is_ready(bmp))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", bmp->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk("Use the sensor to change LED blinking period\n");
|
||||
bmx = DEVICE_DT_GET(DT_NODELABEL(bmx055));
|
||||
if (!device_is_ready(bmx))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", bmx->name);
|
||||
return 0;
|
||||
}
|
||||
LOG_INF("Initialized %s", bmx->name);
|
||||
|
||||
while (1) {
|
||||
ret = sensor_sample_fetch(sensor);
|
||||
if (ret < 0) {
|
||||
lis = DEVICE_DT_GET(DT_NODELABEL(lis2dh));
|
||||
if (!device_is_ready(lis))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", lis->name);
|
||||
return 0;
|
||||
}
|
||||
LOG_INF("Initialized %s", lis->name);
|
||||
|
||||
hdc = DEVICE_DT_GET(DT_NODELABEL(hdc1080));
|
||||
if (!device_is_ready(hdc))
|
||||
{
|
||||
LOG_ERR("Device %s not ready", hdc->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int ret;
|
||||
struct sensor_value voltage, current, pressure, temperature, accel_x, accel_y, accel_z, accel_z_ref, humidity;
|
||||
char str_v[15] = {0};
|
||||
char str_i[15] = {0};
|
||||
char str_p[16] = {0};
|
||||
char str_t[16] = {0};
|
||||
char str_ax[16] = {0};
|
||||
char str_ay[16] = {0};
|
||||
char str_az[16] = {0};
|
||||
char str_az_ref[16] = {0};
|
||||
char str_h[16] = {0};
|
||||
|
||||
ret = sensor_sample_fetch(ina);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not fetch sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(ina, SENSOR_CHAN_VOLTAGE, &voltage);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get voltage (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(ina, SENSOR_CHAN_CURRENT, ¤t);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get current (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = sensor_channel_get(sensor, SENSOR_CHAN_PROX, &val);
|
||||
if (ret < 0) {
|
||||
ret = sensor_sample_fetch(bmp);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not fetch sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(bmp, SENSOR_CHAN_PRESS, &pressure);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get pressure (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
// ret = sensor_channel_get(bmp, SENSOR_CHAN_AMBIENT_TEMP, &temperature);
|
||||
// if (ret < 0)
|
||||
// {
|
||||
// LOG_ERR("Could not get temperature (%d)", ret);
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
ret = sensor_sample_fetch(bmx);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not fetch sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(bmx, SENSOR_CHAN_DIE_TEMP, &temperature);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get temperature (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(bmx, SENSOR_CHAN_ACCEL_X, &accel_x);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get acceleration (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(bmx, SENSOR_CHAN_ACCEL_Y, &accel_y);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get acceleration (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(bmx, SENSOR_CHAN_ACCEL_Z, &accel_z);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get acceleration (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = sensor_sample_fetch(lis);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not fetch sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(lis, SENSOR_CHAN_ACCEL_Z, &accel_z_ref);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get acceleration (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = sensor_sample_fetch(hdc);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not fetch sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(hdc, SENSOR_CHAN_AMBIENT_TEMP, &temperature);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
ret = sensor_channel_get(hdc, SENSOR_CHAN_HUMIDITY, &humidity);
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Could not get sample (%d)", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((last_val.val1 == 0) && (val.val1 == 1)) {
|
||||
if (period_ms == 0U) {
|
||||
period_ms = BLINK_PERIOD_MS_MAX;
|
||||
} else {
|
||||
period_ms -= BLINK_PERIOD_MS_STEP;
|
||||
}
|
||||
sprintf(str_v, "V :%7.5f", voltage.val1 + voltage.val2 * 1e-6);
|
||||
sprintf(str_i, "I :%7.5f", current.val1 + current.val2 * 1e-6);
|
||||
sprintf(str_p, "P :%7.4f", pressure.val1 + pressure.val2 * 1e-6);
|
||||
sprintf(str_t, "T :%7.4f", temperature.val1 + temperature.val2 * 1e-6);
|
||||
sprintf(str_ax, "X :%+7.3f", accel_x.val1 + accel_x.val2 * 1e-6);
|
||||
sprintf(str_ay, "Y :%+7.3f", accel_y.val1 + accel_y.val2 * 1e-6);
|
||||
sprintf(str_az, "Z :%+7.3f", accel_z.val1 + accel_z.val2 * 1e-6);
|
||||
sprintf(str_az_ref, "Zr:%+7.3f", accel_z_ref.val1 + accel_z_ref.val2 * 1e-6);
|
||||
sprintf(str_h, "H :%7.3f", humidity.val1 + humidity.val2 * 1e-6);
|
||||
|
||||
printk("Proximity detected, setting LED period to %u ms\n",
|
||||
period_ms);
|
||||
blink_set_period_ms(blink, period_ms);
|
||||
// printf("%s\t%s\t%s\t%s\n", str_v, str_i, str_p, str_t);
|
||||
|
||||
cfb_framebuffer_clear(dev, false);
|
||||
if (cfb_print(dev, str_t, 0, 0))
|
||||
{
|
||||
printf("Failed to print a string\n");
|
||||
continue;
|
||||
}
|
||||
if (cfb_print(dev, str_h, 0, 16))
|
||||
{
|
||||
printf("Failed to print a string\n");
|
||||
continue;
|
||||
}
|
||||
// if (cfb_print(dev, str_az, 0, 16 * 2))
|
||||
// {
|
||||
// printf("Failed to print a string\n");
|
||||
// continue;
|
||||
// }
|
||||
// if (cfb_print(dev, str_az_ref, 0, 16 * 3))
|
||||
// {
|
||||
// printf("Failed to print a string\n");
|
||||
// continue;
|
||||
// }
|
||||
|
||||
last_val = val;
|
||||
|
||||
k_sleep(K_MSEC(100));
|
||||
cfb_framebuffer_finalize(dev);
|
||||
#if defined(CONFIG_ARCH_POSIX)
|
||||
k_sleep(K_MSEC(20));
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,14 @@
|
||||
|
||||
chosen {
|
||||
zephyr,console = &uart0;
|
||||
// zephyr,shell-uart = &uart0;
|
||||
// zephyr,uart-mcumgr = &uart0;
|
||||
// zephyr,bt-mon-uart = &uart0;
|
||||
// zephyr,bt-c2h-uart = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,uart-mcumgr = &uart0;
|
||||
zephyr,bt-mon-uart = &uart0;
|
||||
zephyr,bt-c2h-uart = &uart0;
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,display = &ssd1306;
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
};
|
||||
|
||||
example_sensor: example-sensor {
|
||||
@ -44,13 +46,86 @@
|
||||
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
|
||||
label = "Yellow LED 3";
|
||||
};
|
||||
led_rx: led_rx {
|
||||
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
|
||||
label = "RX LED";
|
||||
};
|
||||
led_tx: led_tx {
|
||||
gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
|
||||
label = "TX LED";
|
||||
};
|
||||
led_rx_ok: led_rx_ok {
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
label = "RX OK LED";
|
||||
};
|
||||
led_sfd: led_sfd {
|
||||
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
||||
label = "SFD LED";
|
||||
};
|
||||
};
|
||||
|
||||
buttons {
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Pushbutton";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int_drdy: int_drdy {
|
||||
gpios = <&gpio0 22 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "DRDYM from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int1: int_1 {
|
||||
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Interrupt 1 from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int2: int_2 {
|
||||
gpios = <&gpio0 14 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Interrupt 2 from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int3: int_3 {
|
||||
gpios = <&gpio0 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Interrupt 3 from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int4: int_4 {
|
||||
gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Interrupt 4 from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
int5: int_5 {
|
||||
gpios = <&gpio0 30 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Interrupt 5 from BMX055 9-DOF";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
blink_led: blink-led {
|
||||
compatible = "blink-gpio-led";
|
||||
led-gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
|
||||
blink-period-ms = <1000>;
|
||||
};
|
||||
|
||||
/* These aliases are provided for compatibility with samples */
|
||||
aliases {
|
||||
led0 = &led0;
|
||||
led1 = &led1;
|
||||
led2 = &led2;
|
||||
led3 = &led3;
|
||||
// pwm-led0 = &pwm_led0;
|
||||
sw0 = &button0;
|
||||
// sw1 = &button1;
|
||||
// sw2 = &button2;
|
||||
// sw3 = &button3;
|
||||
bootloader-led0 = &led0;
|
||||
mcuboot-button0 = &button0;
|
||||
mcuboot-led0 = &led0;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
};
|
||||
|
||||
&uicr {
|
||||
@ -80,6 +155,53 @@
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-1 = <&i2c0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
ssd1306: ssd1306@3d {
|
||||
compatible = "solomon,ssd1306fb";
|
||||
reg = <0x3d>;
|
||||
width = <128>;
|
||||
height = <64>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <63>;
|
||||
segment-remap;
|
||||
com-invdir;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
|
||||
ina231: ina231@45 {
|
||||
compatible = "ti,ina230";
|
||||
reg = <0x45>;
|
||||
// irq-gpios = <&gpio0 31 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
current-lsb-microamps = <7>;
|
||||
rshunt-micro-ohms = <50000>;
|
||||
adc-mode = "Bus and shunt voltage continuous";
|
||||
};
|
||||
|
||||
bmp388: bmp388@76 {
|
||||
compatible = "bosch,bmp388";
|
||||
reg = <0x76>;
|
||||
int-gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
// odr = "1.563";
|
||||
osr-press = <1>;
|
||||
};
|
||||
|
||||
hdc1080: hdc1080@40 {
|
||||
compatible = "ti,hdc1080";
|
||||
reg = <0x40>;
|
||||
};
|
||||
|
||||
bmx055: bmx055@18 {
|
||||
compatible = "bosch,bmx055";
|
||||
reg = <0x18>;
|
||||
};
|
||||
|
||||
lis2dh: lis2dh@19 {
|
||||
// This is built into the DWM1001 module
|
||||
compatible = "st,lis2dh";
|
||||
reg = <0x19>;
|
||||
};
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
@ -89,3 +211,29 @@
|
||||
pinctrl-1 = <&spi1_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0xc000>;
|
||||
};
|
||||
slot0_partition: partition@c000 {
|
||||
label = "image-0";
|
||||
reg = <0x0000C000 0x37000>;
|
||||
};
|
||||
slot1_partition: partition@43000 {
|
||||
label = "image-1";
|
||||
reg = <0x00043000 0x37000>;
|
||||
};
|
||||
storage_partition: partition@7a000 {
|
||||
label = "storage";
|
||||
reg = <0x0007a000 0x00006000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1,15 +1,19 @@
|
||||
# Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable hardware stack protection
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
# Enable UART console on all configurations for convenience. This is usually
|
||||
# done at board level upstream so that all samples output printed messages to
|
||||
# the configured #zephyr,console. In production boards, this may be enabled at
|
||||
# application level or in a debug configuration overlay.
|
||||
# Enable RTT
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
||||
# enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# enable uart driver
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
# enable console
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
||||
CONFIG_PINCTRL=y
|
||||
|
43
boot.conf
Normal file
43
boot.conf
Normal file
@ -0,0 +1,43 @@
|
||||
CONFIG_PM=n
|
||||
|
||||
CONFIG_BOOT_SIGNATURE_TYPE_NONE=y
|
||||
|
||||
CONFIG_MAIN_STACK_SIZE=10240
|
||||
# CONFIG_MBEDTLS_CFG_FILE="mcuboot-mbedtls-cfg.h"
|
||||
|
||||
CONFIG_BOOT_SWAP_SAVE_ENCTLV=n
|
||||
CONFIG_BOOT_ENCRYPT_IMAGE=n
|
||||
|
||||
CONFIG_BOOT_UPGRADE_ONLY=n
|
||||
CONFIG_BOOT_BOOTSTRAP=n
|
||||
|
||||
### mbedTLS has its own heap
|
||||
# CONFIG_HEAP_MEM_POOL_SIZE is not set
|
||||
|
||||
### We never want Zephyr's copy of tinycrypt. If tinycrypt is needed,
|
||||
### MCUboot has its own copy in tree.
|
||||
# CONFIG_TINYCRYPT is not set
|
||||
# CONFIG_TINYCRYPT_ECC_DSA is not set
|
||||
# CONFIG_TINYCRYPT_SHA256 is not set
|
||||
|
||||
CONFIG_FLASH=y
|
||||
|
||||
### Various Zephyr boards enable features that we don't want.
|
||||
# CONFIG_BT is not set
|
||||
# CONFIG_BT_CTLR is not set
|
||||
# CONFIG_I2C is not set
|
||||
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_MODE_MINIMAL=y # former CONFIG_MODE_MINIMAL
|
||||
### Ensure Zephyr logging changes don't use more resources
|
||||
CONFIG_LOG_DEFAULT_LEVEL=0
|
||||
### Use info log level by default
|
||||
CONFIG_MCUBOOT_LOG_LEVEL_INF=y
|
||||
### Decrease footprint by ~4 KB in comparison to CBPRINTF_COMPLETE=y
|
||||
CONFIG_CBPRINTF_NANO=y
|
||||
### Use the minimal C library to reduce flash usage
|
||||
CONFIG_MINIMAL_LIBC=y
|
||||
|
||||
|
||||
CONFIG_UART_CONSOLE=n
|
||||
CONFIG_MCUBOOT_SERIAL=y
|
@ -2,3 +2,5 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
add_subdirectory_ifdef(CONFIG_EXAMPLE_SENSOR example_sensor)
|
||||
add_subdirectory_ifdef(CONFIG_BMX055 bmx055)
|
||||
add_subdirectory_ifdef(CONFIG_HDC1080 hdc1080)
|
||||
|
@ -3,4 +3,6 @@
|
||||
|
||||
if SENSOR
|
||||
rsource "example_sensor/Kconfig"
|
||||
rsource "bmx055/Kconfig"
|
||||
rsource "hdc1080/Kconfig"
|
||||
endif # SENSOR
|
||||
|
2
drivers/sensor/bmx055/CMakeLists.txt
Normal file
2
drivers/sensor/bmx055/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
zephyr_library()
|
||||
zephyr_library_sources(bmx055.c)
|
17
drivers/sensor/bmx055/Kconfig
Normal file
17
drivers/sensor/bmx055/Kconfig
Normal file
@ -0,0 +1,17 @@
|
||||
config BMX055
|
||||
bool "BMX055"
|
||||
default y
|
||||
depends on DT_HAS_BOSCH_BMX055_ENABLED
|
||||
help
|
||||
Enable driver for BMX055.
|
||||
|
||||
if BMX055
|
||||
|
||||
config BMX055_TRIGGER
|
||||
bool "BMX055 trigger mode"
|
||||
depends on BMX055
|
||||
help
|
||||
Set to enable trigger mode using gpio interrupt, where
|
||||
interrupts are configured to line ALERT PIN.
|
||||
|
||||
endif # BMX055
|
267
drivers/sensor/bmx055/bmx055.c
Normal file
267
drivers/sensor/bmx055/bmx055.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT bosch_bmx055
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(bmx055, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
// Accelerometer registers
|
||||
const uint8_t REG_BWG_CHIPID = 0x00;
|
||||
const uint8_t REG_ACCD_X_LSB = 0x02;
|
||||
const uint8_t REG_ACCD_X_MSB = 0x03;
|
||||
const uint8_t REG_ACCD_Y_LSB = 0x04;
|
||||
const uint8_t REG_ACCD_Y_MSB = 0x05;
|
||||
const uint8_t REG_ACCD_Z_LSB = 0x06;
|
||||
const uint8_t REG_ACCD_Z_MSB = 0x07;
|
||||
const uint8_t REG_ACCD_TEMP = 0x08;
|
||||
const uint8_t REG_INT_STATUS_0 = 0x09;
|
||||
const uint8_t REG_INT_STATUS_1 = 0x0A;
|
||||
const uint8_t REG_INT_STATUS_2 = 0x0B;
|
||||
const uint8_t REG_INT_STATUS_3 = 0x0C;
|
||||
const uint8_t REG_FIFO_STATUS = 0x0E;
|
||||
const uint8_t REG_PMU_RANGE = 0x0F;
|
||||
typedef enum pmu_range_t
|
||||
{
|
||||
PMU_RANGE_2G = 0b0011, ///< DEFAULT
|
||||
PMU_RANGE_4G = 0b0101,
|
||||
PMU_RANGE_8G = 0b1000,
|
||||
PMU_RANGE_16G = 0b1100,
|
||||
} pmu_range_t;
|
||||
const uint8_t REG_PMU_BW = 0x10;
|
||||
typedef enum pmu_bw_t
|
||||
{
|
||||
PMU_BW_8HZ = 0b01000,
|
||||
PMU_BW_16HZ = 0b01001,
|
||||
PMU_BW_31HZ = 0b01010,
|
||||
PMU_BW_63HZ = 0b01011,
|
||||
PMU_BW_125HZ = 0b01100,
|
||||
PMU_BW_250HZ = 0b01101,
|
||||
PMU_BW_500HZ = 0b01110,
|
||||
PMU_BW_1000HZ = 0b01111,
|
||||
} pmu_bw_t;
|
||||
const uint8_t REG_PMU_LPW = 0x11;
|
||||
const uint8_t REG_PMU_LOW_POWER = 0x12;
|
||||
const uint8_t REG_ACCD_HBW = 0x13;
|
||||
const uint8_t REG_BGW_SOFTRESET = 0x14;
|
||||
const uint8_t BGW_SOFTRESET = 0xB6; ///< Soft reset occurs when this value is written to REG_BGW_SOFTRESET
|
||||
const uint8_t REG_INT_EN_0 = 0x16;
|
||||
const uint8_t REG_INT_EN_1 = 0x17;
|
||||
const uint8_t REG_INT_EN_2 = 0x18;
|
||||
const uint8_t REG_INT_MAP_0 = 0x19;
|
||||
const uint8_t REG_INT_MAP_1 = 0x1A;
|
||||
const uint8_t REG_INT_MAP_2 = 0x1B;
|
||||
const uint8_t REG_INT_SRC = 0x1E;
|
||||
const uint8_t REG_INT_OUT_CTRL = 0x20;
|
||||
const uint8_t REG_INT_RST_LATCH = 0x21;
|
||||
const uint8_t REG_INT_0 = 0x22;
|
||||
const uint8_t REG_INT_1 = 0x23;
|
||||
const uint8_t REG_INT_2 = 0x24;
|
||||
const uint8_t REG_INT_3 = 0x25;
|
||||
const uint8_t REG_INT_4 = 0x26;
|
||||
const uint8_t REG_INT_5 = 0x27;
|
||||
const uint8_t REG_INT_6 = 0x28;
|
||||
const uint8_t REG_INT_7 = 0x29;
|
||||
const uint8_t REG_INT_8 = 0x2A;
|
||||
const uint8_t REG_INT_9 = 0x2B;
|
||||
const uint8_t REG_INT_A = 0x2C;
|
||||
const uint8_t REG_INT_B = 0x2D;
|
||||
const uint8_t REG_INT_C = 0x2E;
|
||||
const uint8_t REG_INT_D = 0x2F;
|
||||
const uint8_t REG_FIFO_CONFIG_0 = 0x30;
|
||||
const uint8_t REG_PMU_SELF_TEST = 0x32;
|
||||
const uint8_t REG_TRIM_NVM_CTRL = 0x33;
|
||||
const uint8_t REG_BGW_SPI3_WDT = 0x34;
|
||||
const uint8_t REG_OFC_CTRL = 0x36;
|
||||
const uint8_t REG_OFC_SETTING = 0x37;
|
||||
const uint8_t REG_OFC_OFFSET_X = 0x38;
|
||||
const uint8_t REG_OFC_OFFSET_Y = 0x39;
|
||||
const uint8_t REG_OFC_OFFSET_Z = 0x3A;
|
||||
const uint8_t REG_TRIM_GP0 = 0x3B;
|
||||
const uint8_t REG_TRIM_GP1 = 0x3C;
|
||||
const uint8_t REG_FIFO_CONFIG_1 = 0x3E;
|
||||
const uint8_t REG_FIFO_DATA = 0x3F;
|
||||
|
||||
struct bmx055_data
|
||||
{
|
||||
int16_t accel_x;
|
||||
int16_t accel_y;
|
||||
int16_t accel_z;
|
||||
int16_t gyro_x;
|
||||
int16_t gyro_y;
|
||||
int16_t gyro_z;
|
||||
int8_t temperature;
|
||||
};
|
||||
|
||||
struct bmx055_config
|
||||
{
|
||||
struct i2c_dt_spec bus;
|
||||
#ifdef CONFIG_INA230_TRIGGER
|
||||
bool trig_enabled;
|
||||
uint16_t mask;
|
||||
const struct gpio_dt_spec alert_gpio;
|
||||
uint16_t alert_limit;
|
||||
#endif /* CONFIG_INA230_TRIGGER */
|
||||
};
|
||||
|
||||
static int bmx055_sample_fetch(const struct device *dev,
|
||||
enum sensor_channel chan)
|
||||
{
|
||||
const struct bmx055_config *config = dev->config;
|
||||
struct bmx055_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
uint8_t accel[6];
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_ACCD_X_LSB, accel, sizeof(accel));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read acceleration registers!");
|
||||
return ret;
|
||||
}
|
||||
data->accel_x = ((int16_t)sys_get_le16(&accel[0])) >> 4;
|
||||
data->accel_y = ((int16_t)sys_get_le16(&accel[2])) >> 4;
|
||||
data->accel_z = ((int16_t)sys_get_le16(&accel[4])) >> 4;
|
||||
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_ACCD_TEMP, &data->temperature, sizeof(data->temperature));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read temperature register!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bmx055_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct bmx055_data *data = dev->data;
|
||||
|
||||
switch (chan)
|
||||
{
|
||||
case SENSOR_CHAN_DIE_TEMP:
|
||||
// 0.5K/LSB, center temperature is 23C
|
||||
val->val1 = 23 + data->temperature / 2;
|
||||
val->val2 = 0; // TODO: don't throw out LSB
|
||||
break;
|
||||
case SENSOR_CHAN_ACCEL_X:
|
||||
{
|
||||
float accel = data->accel_x * 0.00098 * 9.80665; // to gees, to m/s^2
|
||||
val->val1 = accel;
|
||||
val->val2 = (accel - val->val1) * 1000000;
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_ACCEL_Y:
|
||||
{
|
||||
float accel = data->accel_y * 0.00098 * 9.80665; // to gees, to m/s^2
|
||||
val->val1 = accel;
|
||||
val->val2 = (accel - val->val1) * 1000000;
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_ACCEL_Z:
|
||||
{
|
||||
// For now assume 2g since that's the default value
|
||||
// 2g 0.98mg/LSB
|
||||
// 4g 1.95mg/LSB
|
||||
// 8g 3.91mg/LSB
|
||||
// 16g 7.81mg/LSB
|
||||
// 1 g = 9.80665 m/s^2
|
||||
float accel = data->accel_z * 0.00098 * 9.80665; // to gees, to m/s^2
|
||||
val->val1 = accel;
|
||||
val->val2 = (accel - val->val1) * 1000000;
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_GYRO_X:
|
||||
case SENSOR_CHAN_GYRO_Y:
|
||||
case SENSOR_CHAN_GYRO_Z:
|
||||
return -ENOTSUP;
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
return -ENOTSUP;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api bmx055_api = {
|
||||
.sample_fetch = &bmx055_sample_fetch,
|
||||
.channel_get = &bmx055_channel_get,
|
||||
};
|
||||
|
||||
static int bmx055_init(const struct device *dev)
|
||||
{
|
||||
const struct bmx055_config *const config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(config->bus.bus))
|
||||
{
|
||||
LOG_ERR("I2C bus %s is not ready", config->bus.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
uint8_t chip_id;
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_BWG_CHIPID, &chip_id, sizeof(chip_id));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read chip ID register!");
|
||||
return ret;
|
||||
}
|
||||
const uint8_t CHIP_ID = 0xfa;
|
||||
if (chip_id != CHIP_ID)
|
||||
{
|
||||
LOG_ERR("Chip ID read from %s incorrect. Read 0x%02X, expected 0x%02X", dev->name, chip_id, CHIP_ID);
|
||||
}
|
||||
|
||||
// // Reset the sensor
|
||||
// uint8_t reset_val = BGW_SOFTRESET;
|
||||
// i2c_burst_write_dt(&config->bus, REG_BGW_SOFTRESET, &reset_val, sizeof(reset_val));
|
||||
|
||||
// // Wait for device to reset
|
||||
|
||||
uint8_t lpw;
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_PMU_LPW, &lpw, sizeof(lpw));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read LPW register!");
|
||||
return ret;
|
||||
}
|
||||
LOG_INF("LPW register: 0x%02X", lpw);
|
||||
|
||||
// Write configuration
|
||||
uint8_t accel_range = PMU_RANGE_2G;
|
||||
i2c_burst_write_dt(&config->bus, REG_PMU_RANGE, &accel_range, sizeof(accel_range));
|
||||
|
||||
uint8_t accel_bw = PMU_BW_8HZ;
|
||||
i2c_burst_write_dt(&config->bus, REG_PMU_BW, &accel_bw, sizeof(accel_bw));
|
||||
|
||||
uint8_t hbw = (1 << 7); // data_high_bw (read filtered data) and enable lsb/msb shadowing
|
||||
i2c_burst_write_dt(&config->bus, REG_ACCD_HBW, &hbw, sizeof(hbw));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BMX055_INIT(i) \
|
||||
static struct bmx055_data bmx055_data_##i; \
|
||||
\
|
||||
static const struct bmx055_config bmx055_config_##i = { \
|
||||
.bus = I2C_DT_SPEC_INST_GET(i), \
|
||||
}; \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(i, &bmx055_init, NULL, \
|
||||
&bmx055_data_##i, \
|
||||
&bmx055_config_##i, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &bmx055_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(BMX055_INIT)
|
2
drivers/sensor/hdc1080/CMakeLists.txt
Normal file
2
drivers/sensor/hdc1080/CMakeLists.txt
Normal file
@ -0,0 +1,2 @@
|
||||
zephyr_library()
|
||||
zephyr_library_sources(hdc1080.c)
|
6
drivers/sensor/hdc1080/Kconfig
Normal file
6
drivers/sensor/hdc1080/Kconfig
Normal file
@ -0,0 +1,6 @@
|
||||
config HDC1080
|
||||
bool "HDC1080"
|
||||
default y
|
||||
depends on DT_HAS_TI_HDC1080_ENABLED
|
||||
help
|
||||
Enable driver for HDC1080.
|
227
drivers/sensor/hdc1080/hdc1080.c
Normal file
227
drivers/sensor/hdc1080/hdc1080.c
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT ti_hdc1080
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(hdc1080, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
const uint8_t REG_TEMPERATURE = 0x00;
|
||||
const uint8_t REG_HUMIDITY = 0x01;
|
||||
const uint8_t REG_CONFIGURATION = 0x02;
|
||||
const uint8_t REG_SERIAL_ID_0 = 0xFB;
|
||||
const uint8_t REG_SERIAL_ID_1 = 0xFC;
|
||||
const uint8_t REG_SERIAL_ID_2 = 0xFD;
|
||||
const uint8_t REG_MANUFACTURER_ID = 0xFE;
|
||||
const uint8_t REG_DEVICE_ID = 0xFF;
|
||||
|
||||
#define CONFIG_RST (1 << 15) ///< Software reset. This bit self clears
|
||||
#define CONFIG_HEAT (1 << 13) ///< Enable heater
|
||||
#define CONFIG_MODE_SEQUENTIAL (1 << 12) ///< Temperature and humidity measured in sequence, temperature first
|
||||
#define CONFIG_BTST (1 << 11) ///< 1 = battery voltage < 2.8V
|
||||
#define CONFIG_TRES_14BIT (0 << 10) ///< Temperature resolution
|
||||
#define CONFIG_TRES_11BIT (1 << 10) ///< Temperature resolution
|
||||
#define CONFIG_HRES_14BIT (0b00 << 8) ///< Humidity resolution
|
||||
#define CONFIG_HRES_11BIT (0b01 << 8) ///< Humidity resolution
|
||||
#define CONFIG_HRES_8BIT (0b10 << 8) ///< Humidity resolution
|
||||
|
||||
struct hdc1080_data
|
||||
{
|
||||
int16_t temperature;
|
||||
uint16_t humidity;
|
||||
};
|
||||
|
||||
struct hdc1080_config
|
||||
{
|
||||
struct i2c_dt_spec bus;
|
||||
uint8_t temperature_bits;
|
||||
uint8_t humidity_bits;
|
||||
};
|
||||
|
||||
static int hdc1080_sample_fetch(const struct device *dev,
|
||||
enum sensor_channel chan)
|
||||
{
|
||||
const struct hdc1080_config *config = dev->config;
|
||||
struct hdc1080_data *data = dev->data;
|
||||
int ret;
|
||||
|
||||
// Trigger measurement
|
||||
uint8_t reg_addr = REG_TEMPERATURE;
|
||||
i2c_write_dt(&config->bus, ®_addr, 1);
|
||||
|
||||
// Wait for conversion
|
||||
float temperature_conversion_time; ///< microseconds
|
||||
switch (config->temperature_bits)
|
||||
{
|
||||
case 11:
|
||||
temperature_conversion_time = 3650;
|
||||
break;
|
||||
case 14:
|
||||
temperature_conversion_time = 6350;
|
||||
break;
|
||||
default:
|
||||
temperature_conversion_time = 0;
|
||||
break;
|
||||
}
|
||||
float humidity_conversion_time; ///< microseconds
|
||||
switch (config->humidity_bits)
|
||||
{
|
||||
case 8:
|
||||
humidity_conversion_time = 2500;
|
||||
break;
|
||||
case 11:
|
||||
humidity_conversion_time = 3850;
|
||||
break;
|
||||
case 14:
|
||||
humidity_conversion_time = 6500;
|
||||
break;
|
||||
default:
|
||||
humidity_conversion_time = 0;
|
||||
break;
|
||||
}
|
||||
k_busy_wait(temperature_conversion_time + humidity_conversion_time);
|
||||
|
||||
// Read data
|
||||
uint8_t rdata[4];
|
||||
ret = i2c_read_dt(&config->bus, rdata, sizeof(rdata));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read temperature and humidity!");
|
||||
return ret;
|
||||
}
|
||||
data->temperature = sys_get_be16(&rdata[0]);
|
||||
data->humidity = sys_get_be16(&rdata[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdc1080_channel_get(const struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct hdc1080_data *data = dev->data;
|
||||
|
||||
switch (chan)
|
||||
{
|
||||
case SENSOR_CHAN_AMBIENT_TEMP:
|
||||
{
|
||||
double temperature = data->temperature * 160.0 / (1 << 16) - 40;
|
||||
val->val1 = temperature;
|
||||
val->val2 = (temperature - val->val1) * 1e6;
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_HUMIDITY:
|
||||
{
|
||||
double humidity = data->humidity * 100.0 / (1 << 16);
|
||||
val->val1 = humidity;
|
||||
val->val2 = (humidity - val->val1) * 1e6;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api hdc1080_api = {
|
||||
.sample_fetch = &hdc1080_sample_fetch,
|
||||
.channel_get = &hdc1080_channel_get,
|
||||
};
|
||||
|
||||
static int hdc1080_init(const struct device *dev)
|
||||
{
|
||||
const struct hdc1080_config *const config = dev->config;
|
||||
int ret;
|
||||
|
||||
if (!device_is_ready(config->bus.bus))
|
||||
{
|
||||
LOG_ERR("I2C bus %s is not ready", config->bus.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
uint8_t id[2];
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_MANUFACTURER_ID, id, sizeof(id));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read manufacturer/device ID registers");
|
||||
return ret;
|
||||
}
|
||||
uint16_t manufacturer_id = sys_get_be16(&id[0]);
|
||||
const uint16_t MANUFACTURER_ID = 0x5449;
|
||||
if (manufacturer_id != MANUFACTURER_ID)
|
||||
{
|
||||
LOG_ERR("Manufacturer ID read from %s incorrect. Read 0x%02X, expected 0x%02X", dev->name, manufacturer_id, MANUFACTURER_ID);
|
||||
}
|
||||
|
||||
ret = i2c_burst_read_dt(&config->bus, REG_DEVICE_ID, id, sizeof(id));
|
||||
if (ret < 0)
|
||||
{
|
||||
LOG_ERR("Failed to read manufacturer/device ID registers");
|
||||
return ret;
|
||||
}
|
||||
uint16_t device_id = sys_get_be16(&id[0]);
|
||||
const uint16_t DEVICE_ID = 0x1050;
|
||||
if (device_id != DEVICE_ID)
|
||||
{
|
||||
LOG_ERR("Device ID read from %s incorrect. Read 0x%02X, expected 0x%02X", dev->name, device_id, DEVICE_ID);
|
||||
}
|
||||
|
||||
// Write configuration
|
||||
uint16_t cfg = 0;
|
||||
switch (config->temperature_bits)
|
||||
{
|
||||
case 14:
|
||||
cfg |= CONFIG_TRES_14BIT;
|
||||
break;
|
||||
case 11:
|
||||
cfg |= CONFIG_TRES_11BIT;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid temperature resolution: %d bits", config->temperature_bits);
|
||||
return -1;
|
||||
}
|
||||
switch (config->humidity_bits)
|
||||
{
|
||||
case 14:
|
||||
cfg |= CONFIG_HRES_14BIT;
|
||||
break;
|
||||
case 11:
|
||||
cfg |= CONFIG_HRES_11BIT;
|
||||
break;
|
||||
case 8:
|
||||
cfg |= CONFIG_HRES_8BIT;
|
||||
break;
|
||||
default:
|
||||
LOG_ERR("Invalid humidity resolution: %d bits", config->humidity_bits);
|
||||
return -1;
|
||||
}
|
||||
uint8_t wdata[2];
|
||||
sys_put_be16(cfg, wdata);
|
||||
i2c_burst_write_dt(&config->bus, REG_CONFIGURATION, wdata, sizeof(wdata));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HDC1080_INIT(i) \
|
||||
static struct hdc1080_data hdc1080_data_##i; \
|
||||
\
|
||||
static const struct hdc1080_config hdc1080_config_##i = { \
|
||||
.bus = I2C_DT_SPEC_INST_GET(i), \
|
||||
.temperature_bits = 14, \
|
||||
.humidity_bits = 14, \
|
||||
}; \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(i, &hdc1080_init, NULL, \
|
||||
&hdc1080_data_##i, \
|
||||
&hdc1080_config_##i, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &hdc1080_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(HDC1080_INIT)
|
12
dts/bindings/sensor/bosch,bmx055.yaml
Normal file
12
dts/bindings/sensor/bosch,bmx055.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
description: |
|
||||
TODO: add a description
|
||||
|
||||
compatible: "bosch,bmx055"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
||||
# properties:
|
||||
# input-gpios:
|
||||
# type: phandle-array
|
||||
# required: true
|
||||
# description: Input GPIO to be sensed.
|
7
dts/bindings/sensor/ti,hdc1080.yaml
Normal file
7
dts/bindings/sensor/ti,hdc1080.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
description: |
|
||||
TODO: add a description
|
||||
|
||||
compatible: "ti,hdc1080"
|
||||
|
||||
include: [sensor-device.yaml, i2c-device.yaml]
|
||||
|
7
west.yml
7
west.yml
@ -8,11 +8,14 @@ manifest:
|
||||
remotes:
|
||||
- name: zephyrproject-rtos
|
||||
url-base: https://github.com/zephyrproject-rtos
|
||||
- name: mcu-tools
|
||||
url-base: https://github.com/mcu-tools
|
||||
|
||||
projects:
|
||||
- name: zephyr
|
||||
remote: zephyrproject-rtos
|
||||
revision: main
|
||||
# revision: v3.6.0
|
||||
import:
|
||||
# By using name-allowlist we can clone only the modules that are
|
||||
# strictly needed by the application.
|
||||
@ -20,3 +23,7 @@ manifest:
|
||||
- cmsis # required by the ARM port
|
||||
- hal_nordic # required by the custom_plank board (Nordic based)
|
||||
- hal_stm32 # required by the nucleo_f302r8 board (STM32 based)
|
||||
- zcbor # required by mcuboot serial
|
||||
- name: mcuboot
|
||||
remote: mcu-tools
|
||||
revision: main
|
||||
|
Reference in New Issue
Block a user