Closed yadon95 closed 2 years ago
Hi @yadon95, Indeed including peripheral drivers into the 2nd stage bootloader is unlikely to work due to dependencies, as you have found. Another factor is that the 2nd stage bootloader is not (safely) updatable. So it is not recommended to put any kind of complex functionality into it, which you might later want to fix.
I can suggest two alternative approaches:
factory
application. ESP-IDF bootloader has support for multiple application slots. You can create 3 partitions in your partition table: factory, ota0, ota1. The 'factory' partition will contain a small ESP-IDF application with CAN bus functionality. There you will receive data over CAN and write it into one of the OTA slots using esp_ota_write
API. You will also need some logic to boot into this application. For example, the default 2nd stage bootloader can enter the factory app based on a GPIO. You can also perform reboot into the factory app by software, from your main app.esp_ota_write
API.Hi @igrr, Thanks for your help, I went for your approach. Currently, I have overwritten the bootloader using the example template to boot on the factory app after the power on restart, and an OTA app if it is a software restart. I've managed to use CAN to get data in. But I have trouble understanding how to properly use the basic OTA functions. I have explored the OTA examples, but they essentially focus on HTTP OTA updates.
So i came up with a list system containing each line. Each line contains 8 bytes of data. To write them to the OTA partition, I've tried to write them using esp_ota_write_with_offset
in a for loop iterating through the line list. I've also added the esp_ota_handle_t handle
with esp_ota_begin(ESP_PARTITION_SUBTYPE_APP_OTA_0, OTA_SIZE_UNKNOWN , &handle);
but i have an error message : E (91406) esp_ota_ops: OTA handle not found.
So, is there more documentation or examples that could be useful regarding the OTA process, the partitions and the bin format for ota_0?
*Here is the code i'm using to write data to OTA ` esp_err_t install_update(line_list update){
esp_err_t error;
esp_ota_handle_t handle;
nvs_flash_init();
printf("starting installation...\n");
esp_partition_t partition;
partition.address = ESP_PARTITION_SUBTYPE_APP_OTA_0;
partition.size = ESP_PARTITION_TABLE_OFFSET;
partition.type = ESP_PARTITION_TYPE_APP;
error = esp_ota_begin(&partition, OTA_SIZE_UNKNOWN , &handle);
printf("Installing update ...\n======================\nUpdate file :\n\n");
for(int i = 1; i < line_list_lenght(update); i++){
debug_print_line_list(update);
error = esp_ota_write_with_offset(handle, *(update -> line -> content), sizeof(update -> line -> content), i);
update = remove_first_line(update);
}
printf("======================\n");
error = esp_ota_end(handle);
return error;
} `
_PS : content
is defined as uint8_t content[8];
_
Cheers!
@yadon95
esp_ota_begin
that might help us understand problem betterHi @mahavirj
I have the following partition table :
Label Usage Type ST Offset Length
nvs WiFi data 01 02 00009000 00004000
otadata OTA data 01 00 0000d000 00002000
phy_init RF data 01 01 0000f000 00001000
factory factory app 00 00 00010000 00100000
ota_0 OTA app 00 10 00110000 00100000
ota_1 OTA app 00 11 00210000 00100000
I've been trying stuff using the code snippet you gave me, and it seems like my esp_ota_begin()
sets an handle (=1), but a null esp_err_t error is returned.
Here is the code i'm using :
// Trying to get ota_0
esp_partition_t * partition;
partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_OTA_0, NULL);
ESP_LOGI("OTA DEBUG", "first ota partition found has subtype %d at offset 0x%x", partition ->subtype, partition -> address);
esp_ota_handle_t handle = 0;
error = esp_ota_begin(partition, OTA_SIZE_UNKNOWN, &handle);
if(error == NULL){
printf("error returned from esp_ota_begin is NULL");
}
char write_buff[10] = {1,2,3,4,5,6,7,8,9,10};
esp_ota_handle_t handle = NULL;
error = esp_ota_begin(partition, OTA_SIZE_UNKNOWN, &handle);
if(handle == NULL){
printf("The handle returned by esp_ota_begin is null\n");
} else {
printf("The handle returned by esp_ota_begin isn't null, it has value : %d\n", handle);
}
error = esp_ota_write(&handle, *write_buff, sizeof(write_buff));
It returns :
I (378) OTA DEBUG: first ota partition found has subtype 16 at offset 0x110000
error returned from esp_ota_begin is NULL
The handle returned by esp_ota_begin isn't null, it has value : 1
E (4378) esp_ota_ops: not found the handle
Is it possible to write 10 known bytes to OTA and then read OTA to check if they are correclly wirten before writting a whole application ?
@yadon95
Please share your entire application and console log that you get from device. I not quite clear from logs that you posted here. It appears code and logs do not match.
Is it possible to write 10 known bytes to OTA and then read OTA to check if they are correclly wirten before writting a whole application ?
Yes. You may use esp_partition_read
to read back contents and verify it against written data
Hi @mahavirj I figured how to make it work, it seems like i had a memry space issue so i created a special 1M partition, and the second was that i needed to erase the parition before writing to it. Thanks for your help.
Just an idea, but I think you don't need a custom bootloader hook to update over CANBUS. I've been able to implement KWP2000 software update on my own TCM utilizing the ESP32. If you are interested, check my code out here:
https://github.com/rnd-ash/ultimate-nag52-fw/tree/can-flashing/src/diag
This works by writing directly to an OTA partition the new code. This also has an advantage that unlike a real ECU, you cannot brick it!
Yes, I don't use a hook anymore, and I think I'm using a kinda similar approach overwriting the 2nd stage bootloader to launch an "update installer" application in certain conditions to download, verify and install the new update to an OTA partition following @igrr 's idea,
Environment
Problem
We are trying to use CAN bus as a way to update our application using it in a bootloader hook (the one after the 2nd stage bootloader) with the OTA data partition. We have started our project using the example bootloader_hook project. The Bootloader's documentation (here) exeplains that we can't use the drivers and other functionalities unless we manually add them. We have tried to add the driver component with the CMake file (REQUIRES driver esp_system freertos) but we still have unresolved includes for freertos/FreeRtos.h and esp_system. The second option described by the documentation is to manually add the needed files to the bootloader_components folder. The problem is that the can driver uses a lot of different imports scattered everywhere. We've also seen someone trying to achieve UART in the bootloader's hoot but using the HAL level instead of the driver level.
Any help would be appreciated, Cheers !!
Source list :
Test project
Bootloader's hook CMakeList.txt
idf_component_register(SRCS "hooks.c" REQUIRES hal freertos driver)
Bootloader's hook.c