接前一篇文章:ICM20948 DMP代码详解(3)
前两回把eMD SmartMotion软件包(eMD-SmartMotion-ICM20948-1.1.1.zip)中的组织结构介绍完了,本回开始正式深入到代码,结合具体代码进行讲解。不过在讲解实际代码之前,再来简要回顾一下:
根目录下的EMD-App文件夹、尤其是其下的EMD-App\src\ICM20948文件夹下是应用代码,也就是实际调用DMP功能的代码。
主要的功能代码是在根目录下的EMD-Core文件夹中。
实际上,整个eMD-SmartMotion-ICM20948-1.1.1.zip工程代码是基于TDK SAMG55开发板的(TDK SAMG55 Dev Kit)。
笔者要使用的是乐鑫的芯片,故而需要将代码移植到乐鑫平台上。因此,这里重点并不关注平台相关代码,而只关注平台无关代码,尤其是EMP-Core下的代码即驱动代码。
不过,凡事总要有源头,得打头说起。eMD-SmartMotion-ICM20948-1.1.1工程的头即入口点在EMD-App\src\ICM20948\main.c中(main.c也就是入口文件),入口点当然是主函数main()。代码如下:
int main (void)
{
int rc = 0;
/* Hardware initialization */
sysclk_init();
board_init();
sysclk_enable_peripheral_clock(ID_TC0);
/* Configure Device - Host Interface */
configure_console();
#ifdef INV_MSG_ENABLE
/* Setup message logging */
INV_MSG_SETUP(INV_MSG_ENABLE, msg_printer);
#endif
INV_MSG(INV_MSG_LEVEL_INFO, "##########################");
INV_MSG(INV_MSG_LEVEL_INFO, " ICM20948 example ");
INV_MSG(INV_MSG_LEVEL_INFO, " Ver: %s", EMD_RELEASE_VERSION_STRING);
INV_MSG(INV_MSG_LEVEL_INFO, "##########################");
/* Initialize External Sensor Interrupt */
ext_int_initialize(&ext_interrupt_handler);
interface_initialize();
/* Configure sysTick Timer */
SysTick_Config(sysclk_get_cpu_hz() / MILLISECONDS_PER_SECOND);
/*
* Initialize icm20948 serif structure
*/
struct inv_icm20948_serif icm20948_serif;
icm20948_serif.context = 0; /* no need */
icm20948_serif.read_reg = idd_io_hal_read_reg;
icm20948_serif.write_reg = idd_io_hal_write_reg;
icm20948_serif.max_read = 1024*16; /* maximum number of bytes allowed per serial read */
icm20948_serif.max_write = 1024*16; /* maximum number of bytes allowed per serial write */
icm20948_serif.is_spi = interface_is_SPI();
/*
* Reset icm20948 driver states
*/
inv_icm20948_reset_states(&icm_device, &icm20948_serif);
inv_icm20948_register_aux_compass(&icm_device, INV_ICM20948_COMPASS_ID_AK09916, AK0991x_DEFAULT_I2C_ADDR);
/*
* Setup the icm20948 device
*/
rc = icm20948_sensor_setup();
/*
* Now that Icm20948 device was initialized, we can proceed with DMP image loading
* This step is mandatory as DMP image are not store in non volatile memory
*/
rc += load_dmp3();
check_rc(rc, "Error sensor_setup/DMP loading.");
/*
* Initialize Dynamic protocol stuff
*/
DynProTransportUart_init(&transport, iddwrapper_transport_event_cb, 0);
DynProtocol_init(&protocol, iddwrapper_protocol_event_cb, 0);
InvScheduler_init(&scheduler);
InvScheduler_initTask(&scheduler, &commandHandlerTask, "commandHandlerTask", CommandHandlerTaskMain, 0, INVSCHEDULER_TASK_PRIO_MIN, 1);
InvScheduler_initTask(&scheduler, &blinkerLedTask, "blinkerLedTask", BlinkerLedTaskMain, 0, INVSCHEDULER_TASK_PRIO_MIN+1, 1000000/SCHEDULER_PERIOD);
InvScheduler_startTask(&blinkerLedTask, 0);
InvScheduler_startTask(&commandHandlerTask, 0);
hw_timer_start(20); // Start the timestamp timer at 20 Hz.
while (1) {
InvScheduler_dispatchTasks(&scheduler);
if (irq_from_device == 1) {
inv_icm20948_poll_sensor(&icm_device, (void *)0, build_sensor_event_data);
__disable_irq();
irq_from_device = 0;
__enable_irq();
}
}
return 0;
}
上边已提到,工程代码是基于TDK SAMG55开发板的,因此涉及到系统初始化、外设初始化等部分这里不重点关注,只需要将i2c以及时钟、定时器、延时、中断等“对到”乐鑫ESP32系列模组中即可。
那么,真正开始关注的代码是从以下部分开始的:
/*
* Initialize icm20948 serif structure
*/
struct inv_icm20948_serif icm20948_serif;
icm20948_serif.context = 0; /* no need */
icm20948_serif.read_reg = idd_io_hal_read_reg;
icm20948_serif.write_reg = idd_io_hal_write_reg;
icm20948_serif.max_read = 1024*16; /* maximum number of bytes allowed per serial read */
icm20948_serif.max_write = 1024*16; /* maximum number of bytes allowed per serial write */
icm20948_serif.is_spi = interface_is_SPI();
下一回开始,要真正解析每一段代码了。