Da Vinci Firmware 1
Firmware for the DaVinci-M rocket avionics board.
Loading...
Searching...
No Matches
STM32H7xx SPI Platform Specific Functions

Functions to connect LIS2MDL driver to STM32H7xx SPI HAL. More...

Collaboration diagram for STM32H7xx SPI Platform Specific Functions:

Functions

static int32_t platform_spi_write (void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
 Write data to LIS2MDL sensor via SPI.
 
static int32_t platform_spi_read (void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
 Read data from LIS2MDL sensor via SPI.
 
int32_t lis2mdl_init (stmdev_ctx_t *ctx)
 Initialize the LIS2MDL sensor.
 
int32_t lis2mdl_init_2 (stmdev_ctx_t *ctx)
 

Detailed Description

Functions to connect LIS2MDL driver to STM32H7xx SPI HAL.

Function Documentation

◆ lis2mdl_init()

int32_t lis2mdl_init ( stmdev_ctx_t ctx)

Initialize the LIS2MDL sensor.

Parameters
ctxSensor context with SPI handle and platform functions
Return values
0if OK, -1 if error or WHO_AM_I mismatch

Definition at line 1461 of file lis2mdl_reg.c.

1462{
1463 uint8_t who_am_i = 0;
1464 uint8_t val = 0; // Temporary variable for get functions
1465 lis2mdl_cfg_reg_a_t cfg_a;
1466 lis2mdl_cfg_reg_c_t cfg_c;
1467
1468
1469 if (ctx == NULL) return -1;
1470
1471
1474 ctx->handle = &hspi2; // Your SPI_HandleTypeDef
1475
1476 // Check WHO_AM_I register
1477 if (lis2mdl_device_id_get(ctx, &who_am_i) != 0) return -1; // Error reading WHO_AM_I
1478 if (who_am_i != LIS2MDL_ID){
1479 return -1;
1480 } // WHO_AM_I mismatch (LIS2MDL_ID should be 0x40 as per datasheet)
1481
1482 // Perform a software reset
1483 if (lis2mdl_reset_set(ctx, 1) != 0) return -1;
1484 platform_delay(5); // Wait for reset to complete (datasheet doesn't specify, 5ms is a guess)
1485 do {
1486 if (lis2mdl_reset_get(ctx, &val) != 0) return -1;
1487 } while (val); // Poll SOFT_RST bit until it is cleared
1488
1489
1490 // Reboot memory content to reload calibration parameters
1491 if (lis2mdl_boot_set(ctx, 1) != 0) return -1;
1492 platform_delay(5); // Wait for boot to complete
1493 do {
1494 if (lis2mdl_boot_get(ctx, &val) != 0) return -1;
1495 } while (val); // Poll REBOOT bit until it is cleared
1496
1497 // Configure for 4-wire SPI mode
1498 // Note: The LIS2MDL CS pin (pin 3) must be tied LOW to enable SPI mode.
1499 // This function configures the 4WSPI bit in CFG_REG_C for the SDO line.
1500 if (lis2mdl_spi_mode_set(ctx, LIS2MDL_SPI_4_WIRE) != 0) return -1;
1501
1502
1503 // Configure CFG_REG_A for:
1504 // - Temperature compensation enabled
1505 // - Continuous mode
1506 // - ODR 10 Hz
1507 // - High-resolution mode
1508 // This matches the datasheet startup example (CFG_REG_A = 0x80)
1509
1510 // Method 1: Using individual set functions (less efficient due to multiple R-M-W)
1511 // if (lis2mdl_offset_temp_comp_set(ctx, 1) != 0) return -1;
1512 // if (lis2mdl_operating_mode_set(ctx, LIS2MDL_CONTINUOUS_MODE) != 0) return -1;
1513 // if (lis2mdl_data_rate_set(ctx, LIS2MDL_ODR_10HZ) != 0) return -1; // Assuming LIS2MDL_ODR_10HZ is defined
1514 // if (lis2mdl_power_mode_set(ctx, LIS2MDL_HIGH_RESOLUTION) != 0) return -1;
1515
1516 // Method 2: Direct write to CFG_REG_A (more efficient)
1517 cfg_a.comp_temp_en = 1;
1518 cfg_a.reboot = 0;
1519 cfg_a.soft_rst = 0;
1520 cfg_a.lp = (uint8_t)LIS2MDL_HIGH_RESOLUTION; // Assuming LIS2MDL_HIGH_RESOLUTION = 0
1521 cfg_a.odr = (uint8_t)LIS2MDL_ODR_10Hz; // Assuming LIS2MDL_ODR_10Hz = 0
1522 cfg_a.md = (uint8_t)LIS2MDL_CONTINUOUS_MODE; // Assuming LIS2MDL_CONTINUOUS_MODE = 0
1523 if (lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&cfg_a, 1) != 0) return -1;
1524
1525
1526 // Configure CFG_REG_C for:
1527 // - Block Data Update (BDU) enabled
1528 // - Data Ready signal on INT/DRDY pin enabled (optional, as per datasheet startup example)
1529 // - 4-wire SPI is already set by lis2mdl_spi_mode_set above.
1530
1531 // Method 1: Using individual set functions
1532 // if (lis2mdl_block_data_update_set(ctx, 1) != 0) return -1;
1533 // if (lis2mdl_drdy_on_pin_set(ctx, 1) != 0) return -1; // Optional: enable DRDY on pin
1534
1535 // Method 2: Direct write to CFG_REG_C (more efficient, considers 4WSPI already set)
1536 if (lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&cfg_c, 1) != 0) return -1;
1537 cfg_c.bdu = 1;
1538 cfg_c.drdy_on_pin = 1; // Enable DRDY on pin as per datasheet example
1539 // cfg_c._4wspi is already set by lis2mdl_spi_mode_set, no need to change it here
1540 // unless lis2mdl_spi_mode_set is not called before this.
1541 // For safety, ensure it's set if not using the dedicated function earlier:
1542 // cfg_c._4wspi = 1; // If LIS2MDL_SPI_4_WIRE is desired
1543 cfg_c.i2c_dis = 1; // Disable I2C if exclusively using SPI
1544 cfg_c.int_on_pin = 0; // Disable interrupt on pin unless specifically needed
1545 cfg_c.self_test = 0; // Disable self-test
1546 cfg_c.ble = (uint8_t)LIS2MDL_LSB_AT_LOW_ADD; // Default data format
1547
1548 if (lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&cfg_c, 1) != 0) return -1;
1549
1550
1551 // Sensor is now initialized with basic settings.
1552 // Further configuration (e.g., interrupts, thresholds) can be done as needed.
1553 return 0; // Success
1554}
#define NULL
Definition bmp3_defs.h:88
SPI_HandleTypeDef hspi2
HAL SPI handle for Sensor Bus 1 (e.g., IMU, Baro).
Definition main.c:62
int32_t __weak lis2mdl_write_reg(const stmdev_ctx_t *ctx, uint8_t reg, uint8_t *data, uint16_t len)
Write generic device register.
Definition lis2mdl_reg.c:92
int32_t __weak lis2mdl_read_reg(const stmdev_ctx_t *ctx, uint8_t reg, uint8_t *data, uint16_t len)
Read generic device register.
Definition lis2mdl_reg.c:66
static int32_t platform_spi_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
Write data to LIS2MDL sensor via SPI.
static int32_t platform_spi_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
Read data from LIS2MDL sensor via SPI.
int32_t lis2mdl_boot_get(const stmdev_ctx_t *ctx, uint8_t *val)
Reboot memory content. Reload the calibration parameters.[get].
int32_t lis2mdl_reset_get(const stmdev_ctx_t *ctx, uint8_t *val)
Software reset. Restore the default values in user registers.[get].
int32_t lis2mdl_reset_set(const stmdev_ctx_t *ctx, uint8_t val)
Software reset. Restore the default values in user registers.[set].
int32_t lis2mdl_device_id_get(const stmdev_ctx_t *ctx, uint8_t *buff)
DeviceWhoamI.[get].
int32_t lis2mdl_boot_set(const stmdev_ctx_t *ctx, uint8_t val)
Reboot memory content. Reload the calibration parameters.[set].
int32_t lis2mdl_spi_mode_set(const stmdev_ctx_t *ctx, lis2mdl_sim_t val)
SPI Serial Interface Mode selection.[set].
#define LIS2MDL_CFG_REG_C
#define LIS2MDL_CFG_REG_A
@ LIS2MDL_ODR_10Hz
@ LIS2MDL_SPI_4_WIRE
@ LIS2MDL_LSB_AT_LOW_ADD
@ LIS2MDL_HIGH_RESOLUTION
@ LIS2MDL_CONTINUOUS_MODE
#define LIS2MDL_ID
#define platform_delay(ms)
Definition lis2mdl_reg.c:32
stmdev_read_ptr read_reg
stmdev_write_ptr write_reg

References lis2mdl_cfg_reg_c_t::bdu, lis2mdl_cfg_reg_c_t::ble, lis2mdl_cfg_reg_a_t::comp_temp_en, lis2mdl_cfg_reg_c_t::drdy_on_pin, stmdev_ctx_t::handle, hspi2, lis2mdl_cfg_reg_c_t::i2c_dis, lis2mdl_cfg_reg_c_t::int_on_pin, lis2mdl_boot_get(), lis2mdl_boot_set(), LIS2MDL_CFG_REG_A, LIS2MDL_CFG_REG_C, LIS2MDL_CONTINUOUS_MODE, lis2mdl_device_id_get(), LIS2MDL_HIGH_RESOLUTION, LIS2MDL_ID, LIS2MDL_LSB_AT_LOW_ADD, LIS2MDL_ODR_10Hz, lis2mdl_read_reg(), lis2mdl_reset_get(), lis2mdl_reset_set(), LIS2MDL_SPI_4_WIRE, lis2mdl_spi_mode_set(), lis2mdl_write_reg(), lis2mdl_cfg_reg_a_t::lp, lis2mdl_cfg_reg_a_t::md, NULL, lis2mdl_cfg_reg_a_t::odr, platform_delay, platform_spi_read(), platform_spi_write(), stmdev_ctx_t::read_reg, lis2mdl_cfg_reg_a_t::reboot, lis2mdl_cfg_reg_c_t::self_test, lis2mdl_cfg_reg_a_t::soft_rst, and stmdev_ctx_t::write_reg.

Here is the call graph for this function:

◆ lis2mdl_init_2()

int32_t lis2mdl_init_2 ( stmdev_ctx_t ctx)

Definition at line 1556 of file lis2mdl_reg.c.

1557{
1558 uint8_t who_am_i = 0;
1559 uint8_t val = 0; // Temporary variable for get functions
1560 lis2mdl_cfg_reg_a_t cfg_a;
1561 lis2mdl_cfg_reg_c_t cfg_c;
1562
1563
1564 if (ctx == NULL) return -1;
1565
1566
1569 ctx->handle = &hspi3; // Your SPI_HandleTypeDef
1570
1571 // Check WHO_AM_I register
1572 if (lis2mdl_device_id_get(ctx, &who_am_i) != 0) return -1; // Error reading WHO_AM_I
1573 if (who_am_i != LIS2MDL_ID) return -1; // WHO_AM_I mismatch (LIS2MDL_ID should be 0x40 as per datasheet)
1574
1575 // Perform a software reset
1576 if (lis2mdl_reset_set(ctx, 1) != 0) return -1;
1577 platform_delay(5); // Wait for reset to complete (datasheet doesn't specify, 5ms is a guess)
1578 do {
1579 if (lis2mdl_reset_get(ctx, &val) != 0) return -1;
1580 } while (val); // Poll SOFT_RST bit until it is cleared
1581
1582
1583 // Reboot memory content to reload calibration parameters
1584 if (lis2mdl_boot_set(ctx, 1) != 0) return -1;
1585 platform_delay(5); // Wait for boot to complete
1586 do {
1587 if (lis2mdl_boot_get(ctx, &val) != 0) return -1;
1588 } while (val); // Poll REBOOT bit until it is cleared
1589
1590 // Configure for 4-wire SPI mode
1591 // Note: The LIS2MDL CS pin (pin 3) must be tied LOW to enable SPI mode.
1592 // This function configures the 4WSPI bit in CFG_REG_C for the SDO line.
1593 if (lis2mdl_spi_mode_set(ctx, LIS2MDL_SPI_4_WIRE) != 0) return -1;
1594
1595
1596 // Configure CFG_REG_A for:
1597 // - Temperature compensation enabled
1598 // - Continuous mode
1599 // - ODR 10 Hz
1600 // - High-resolution mode
1601 // This matches the datasheet startup example (CFG_REG_A = 0x80)
1602
1603 // Method 1: Using individual set functions (less efficient due to multiple R-M-W)
1604 // if (lis2mdl_offset_temp_comp_set(ctx, 1) != 0) return -1;
1605 // if (lis2mdl_operating_mode_set(ctx, LIS2MDL_CONTINUOUS_MODE) != 0) return -1;
1606 // if (lis2mdl_data_rate_set(ctx, LIS2MDL_ODR_10HZ) != 0) return -1; // Assuming LIS2MDL_ODR_10HZ is defined
1607 // if (lis2mdl_power_mode_set(ctx, LIS2MDL_HIGH_RESOLUTION) != 0) return -1;
1608
1609 // Method 2: Direct write to CFG_REG_A (more efficient)
1610 cfg_a.comp_temp_en = 1;
1611 cfg_a.reboot = 0;
1612 cfg_a.soft_rst = 0;
1613 cfg_a.lp = (uint8_t)LIS2MDL_HIGH_RESOLUTION; // Assuming LIS2MDL_HIGH_RESOLUTION = 0
1614 cfg_a.odr = (uint8_t)LIS2MDL_ODR_10Hz; // Assuming LIS2MDL_ODR_10Hz = 0
1615 cfg_a.md = (uint8_t)LIS2MDL_CONTINUOUS_MODE; // Assuming LIS2MDL_CONTINUOUS_MODE = 0
1616 if (lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&cfg_a, 1) != 0) return -1;
1617
1618
1619 // Configure CFG_REG_C for:
1620 // - Block Data Update (BDU) enabled
1621 // - Data Ready signal on INT/DRDY pin enabled (optional, as per datasheet startup example)
1622 // - 4-wire SPI is already set by lis2mdl_spi_mode_set above.
1623
1624 // Method 1: Using individual set functions
1625 // if (lis2mdl_block_data_update_set(ctx, 1) != 0) return -1;
1626 // if (lis2mdl_drdy_on_pin_set(ctx, 1) != 0) return -1; // Optional: enable DRDY on pin
1627
1628 // Method 2: Direct write to CFG_REG_C (more efficient, considers 4WSPI already set)
1629 if (lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&cfg_c, 1) != 0) return -1;
1630 cfg_c.bdu = 1;
1631 cfg_c.drdy_on_pin = 1; // Enable DRDY on pin as per datasheet example
1632 // cfg_c._4wspi is already set by lis2mdl_spi_mode_set, no need to change it here
1633 // unless lis2mdl_spi_mode_set is not called before this.
1634 // For safety, ensure it's set if not using the dedicated function earlier:
1635 // cfg_c._4wspi = 1; // If LIS2MDL_SPI_4_WIRE is desired
1636 cfg_c.i2c_dis = 1; // Disable I2C if exclusively using SPI
1637 cfg_c.int_on_pin = 0; // Disable interrupt on pin unless specifically needed
1638 cfg_c.self_test = 0; // Disable self-test
1639 cfg_c.ble = (uint8_t)LIS2MDL_LSB_AT_LOW_ADD; // Default data format
1640
1641 if (lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&cfg_c, 1) != 0) return -1;
1642
1643
1644 // Sensor is now initialized with basic settings.
1645 // Further configuration (e.g., interrupts, thresholds) can be done as needed.
1646 return 0; // Success
1647}
SPI_HandleTypeDef hspi3
HAL SPI handle for Sensor Bus 2 (e.g., secondary sensors).
Definition main.c:63

References lis2mdl_cfg_reg_c_t::bdu, lis2mdl_cfg_reg_c_t::ble, lis2mdl_cfg_reg_a_t::comp_temp_en, lis2mdl_cfg_reg_c_t::drdy_on_pin, stmdev_ctx_t::handle, hspi3, lis2mdl_cfg_reg_c_t::i2c_dis, lis2mdl_cfg_reg_c_t::int_on_pin, lis2mdl_boot_get(), lis2mdl_boot_set(), LIS2MDL_CFG_REG_A, LIS2MDL_CFG_REG_C, LIS2MDL_CONTINUOUS_MODE, lis2mdl_device_id_get(), LIS2MDL_HIGH_RESOLUTION, LIS2MDL_ID, LIS2MDL_LSB_AT_LOW_ADD, LIS2MDL_ODR_10Hz, lis2mdl_read_reg(), lis2mdl_reset_get(), lis2mdl_reset_set(), LIS2MDL_SPI_4_WIRE, lis2mdl_spi_mode_set(), lis2mdl_write_reg(), lis2mdl_cfg_reg_a_t::lp, lis2mdl_cfg_reg_a_t::md, NULL, lis2mdl_cfg_reg_a_t::odr, platform_delay, platform_spi_read(), platform_spi_write(), stmdev_ctx_t::read_reg, lis2mdl_cfg_reg_a_t::reboot, lis2mdl_cfg_reg_c_t::self_test, lis2mdl_cfg_reg_a_t::soft_rst, and stmdev_ctx_t::write_reg.

Here is the call graph for this function:

◆ platform_spi_read()

static int32_t platform_spi_read ( void *  handle,
uint8_t  reg,
uint8_t *  bufp,
uint16_t  len 
)
static

Read data from LIS2MDL sensor via SPI.

Parameters
handlePointer to SPI_HandleTypeDef (passed via stmdev_ctx_t)
regRegister address to read from
bufpPointer to data buffer to store read data
lenNumber of bytes to read
Return values
0if OK, -1 if error

Definition at line 1418 of file lis2mdl_reg.c.

1419{
1420 SPI_HandleTypeDef *spi_handle = (SPI_HandleTypeDef *)handle;
1421 uint8_t cmd_byte;
1422
1423 if (spi_handle == NULL || bufp == NULL) {
1424 return -1; // Invalid arguments
1425 }
1426
1427 // LIS2MDL SPI read command: MSB=1 for read, followed by 7-bit register address
1428 cmd_byte = (reg & 0x7F) | 0x80; // Set MSB to 1 for read
1429
1430
1431 if(HAL_GPIO_ReadPin(IMU_CS_GPIO_Port,IMU_CS_Pin)!=GPIO_PIN_SET){IMU_CS_HIGH;}
1432 if(HAL_GPIO_ReadPin(BARO_CS_GPIO_Port,BARO_CS_Pin)!=GPIO_PIN_SET){BMP390_CS_HIGH;}
1433 // Pull CS pin low to select the device
1434 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_RESET);
1435
1436 // Transmit the command byte (register address with read flag)
1437 if (HAL_SPI_Transmit(spi_handle, &cmd_byte, 1, LIS2MDL_SPI_TIMEOUT) != HAL_OK)
1438 {
1439 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET); // Release CS
1440 return -1; // SPI transmission error
1441 }
1442
1443 // Receive the data
1444 if (HAL_SPI_Receive(spi_handle, bufp, len, LIS2MDL_SPI_TIMEOUT) != HAL_OK)
1445 {
1446 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET); // Release CS
1447 return -1; // SPI reception error
1448 }
1449
1450 // Pull CS pin high to deselect the device
1451 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET);
1452
1453 return 0; // Success
1454}
#define LIS2MDL_CS_GPIO_Port
Definition lis2mdl_reg.c:24
#define LIS2MDL_CS_Pin
Definition lis2mdl_reg.c:27
#define LIS2MDL_SPI_TIMEOUT
Definition lis2mdl_reg.c:36
@ HAL_OK

References HAL_OK, LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, LIS2MDL_SPI_TIMEOUT, and NULL.

Referenced by lis2mdl_init(), and lis2mdl_init_2().

Here is the caller graph for this function:

◆ platform_spi_write()

static int32_t platform_spi_write ( void *  handle,
uint8_t  reg,
const uint8_t *  bufp,
uint16_t  len 
)
static

Write data to LIS2MDL sensor via SPI.

Parameters
handlePointer to SPI_HandleTypeDef (passed via stmdev_ctx_t)
regRegister address to write to
bufpPointer to data buffer to write
lenNumber of bytes to write
Return values
0if OK, -1 if error

Definition at line 1372 of file lis2mdl_reg.c.

1373{
1374 SPI_HandleTypeDef *spi_handle = (SPI_HandleTypeDef *)handle;
1375 uint8_t cmd_byte;
1376
1377 if (spi_handle == NULL || bufp == NULL) {
1378 return -1; // Invalid arguments
1379 }
1380
1381 // LIS2MDL SPI write command: MSB=0 for write, followed by 7-bit register address
1382 cmd_byte = reg & 0x7F; // Ensure MSB is 0 for write
1383
1384 BMP390_CS_HIGH;
1385 IMU_CS_HIGH;
1386 // Pull CS pin low to select the device
1387 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_RESET);
1388
1389
1390 // Transmit the command byte (register address with write flag)
1391 if (HAL_SPI_Transmit(spi_handle, &cmd_byte, 1, LIS2MDL_SPI_TIMEOUT) != HAL_OK)
1392 {
1393 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET); // Release CS
1394 return -1; // SPI transmission error
1395 }
1396
1397 // Transmit the data
1398 if (HAL_SPI_Transmit(spi_handle, (uint8_t*)bufp, len, LIS2MDL_SPI_TIMEOUT) != HAL_OK)
1399 {
1400 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET); // Release CS
1401 return -1; // SPI transmission error
1402 }
1403
1404 // Pull CS pin high to deselect the device
1405 HAL_GPIO_WritePin(LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, GPIO_PIN_SET);
1406
1407 return 0; // Success
1408}

References HAL_OK, LIS2MDL_CS_GPIO_Port, LIS2MDL_CS_Pin, LIS2MDL_SPI_TIMEOUT, and NULL.

Referenced by lis2mdl_init(), and lis2mdl_init_2().

Here is the caller graph for this function: