Тёмный

Worlds Simplest Bootloader :: Bare Metal Programming Series 4 

Low Byte Productions
Подписаться 78 тыс.
Просмотров 23 тыс.
50% 1

Опубликовано:

 

28 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 44   
@stevezhou184
@stevezhou184 8 месяцев назад
like your video so much. bootloader is flying everywhere, but nobody explains exactly what "bootloader" is. This is problem of software, everyone coins their own concept, then use the popular NAME to name it. like your clearness
@ivsuk
@ivsuk 9 месяцев назад
Thank you very much. Very clear and articulate explanation. My windows toolchain with stlink debug on WSL was a bit tricky but got there in the end. Anyone struggling: multiarch-gdb symlinked to arm + usbipd.
@alexyoung6418
@alexyoung6418 Год назад
I like how you linked two otherwise separated projects together to paint a complete picture of how they are allocated in the memory and how they work together, or at least not against each other. It's worth pointing out that some applications also jump back to the bootloader to trigger the firmware update feature. Assuming the worst scenario where main application hadn't done a good cleanup by resetting the interrupt vector offset register, it's recommended to force reset that exact register in the very beginning of the bootloader execution.
@LowByteProductions
@LowByteProductions Год назад
Great point, the bootloader should also explicitly set the vector table offset.
@CuriousCyclist
@CuriousCyclist 10 месяцев назад
Thank you for taking the time to make this video. Really good educational content. 👍
@フィリップフーベル
@フィリップフーベル 11 месяцев назад
Again, I realy like your project! Some improvement-suggestions: to really understand the content of the jump_to_main function (better name would be jump_to_app_main), it is essential that the listener understand that the linker will do all the main work for us. The address of the jump_fn which we are digging out of the addresses with the pointer joggling is correct BECAUSE the linker puts it there (will/has put it there) with the linker script of the app.
@anshulmaurya6913
@anshulmaurya6913 10 месяцев назад
It's been done really really nicely - Thank You
@stevekoehn1675
@stevekoehn1675 11 месяцев назад
Your thinking is so clear, your explanations so clear and logical I Get It! (I'm older and learning on my own so I need all the help I can get, ha)
@AbidAli-mj8cu
@AbidAli-mj8cu 7 месяцев назад
At @46:51, the first 4 bytes represents Main stack pointer, which is end of the RAM (from where stack starts), 0x20000000U + 0x18000U (96KB) = 0x20018000U
@nhanNguyen-wo8fy
@nhanNguyen-wo8fy 6 месяцев назад
10:30 flash memory 15:50 fix make file 17:10 what bootloader do 50:40 main 59:30 vector table offset register
@lorito6995
@lorito6995 20 дней назад
many thanks!
@u0000-u2x
@u0000-u2x Год назад
Amazing content as usual. Thank you for sharing.
@johnhansson8646
@johnhansson8646 8 месяцев назад
Regarding the padding of the bootloader to 32kb, couldn’t you configure that in your linker script, so that it is done for you when linking?
@john999
@john999 Год назад
Thank you very much for your tutorial. It is so kind of you, to give us this free and easy to understand introduction into bootloaders. When I started to experiment with bootloaders, I was overwhelmed by the whole documentation of the chip. And of course it did not work, so I was thrown off, not knowing why it failed. With this start-to-finish mini-demo it is a lot easier to get going and building from that on forward. Would be nice if you could mention some ways of including your handmade changes of the linker script to IDEs (e.g. Eclipse). Like, where you can use the settings of the project to change the memory layout or add sections. Maybe this helps other to include your bootloader to their current project w/o too much editing of linker files that are handled by the autogen of the IDE.
@LowByteProductions
@LowByteProductions Год назад
Thank you John. Indeed - I'll point out whenever I'm making changes to linkerscripts etc, and what those changes imply. As for playing well with other IDEs, I'm not sure how much help I can be 😄 I try to avoid eclipse wherever I can! I am familiar with STM32CubeIDE however, and how it can be configured to use a makefile build, which gives a lot more control. There are still autogenerated files to deal with, but typically the linkerscript is not one of the files which is not regenerated across builds. I'll add it to the list of future topics.
@bobweiram6321
@bobweiram6321 2 месяца назад
Is it possible to pad the bootloader using the assembler. You can create a data section and then include your bin .
@kilwo
@kilwo Год назад
Just wondering why you do a C++ function call in the bootloader? If you did an assembly jump (branch I think in ARM) then you could reset the vector table offset address before the jump and the main app wouldn't need to know anything about the size of the bootloader. The main app would just work as if it was the only thing in memory and you could change the bootloader size without needing to update the main app.
@LowByteProductions
@LowByteProductions Год назад
First of all, thanks for taking the time to comment! I'm not sure what you mean by a C++ function call. Where possible I'm trying to avoid inline assembly - the compiler is usually (like 99% of the time) smart enough to do the right thing when expressed in C. For example, the process for getting the address of the reset vector, casting it to a void (*)(void) function pointer and calling it, results in basically the assembly you describe; figuring out an offset, getting the reset vector address indirectly, and using a bx (branch) instruction to jump to it. Your point about setting the vector table offset in the bootloader is a really good suggestion - I guess that does make a lot more sense!
@kilwo
@kilwo Год назад
@@LowByteProductions Thanks for taking the time to make the videos! I really enjoy low level stuff. Sorry, my thoughts were not 100% clear. The C++ function call I was referring to was just the fact that you cast the pointer into a function, and then call that. The reason I was thinking this should be an unconditional jump, or equivalent, was because a function call effects the stack, where a jump doesn’t. At least in the processors I have used. Once you have changed the vector offset register, you don’t want to do a call that will push onto the stack, as it will never be returned and will waste memory. Keep up the great videos.
@LowByteProductions
@LowByteProductions Год назад
Ah OK I see what you mean. The C++ threw me off there - I don't think there is a relation to C++ here. You're right that you'll end up with an unecessary stack frame, but one of the first things that happens in the reset vector for both the bootloader and the main application is setting the stack pointer to an explicit value. That has the effect of essentially removing tany stack frames that would have been there previously, and so doing a cast/call isn't a problem. And even so, no arguments or other information is pushed to the stack (at least the way this is currently compiled), as the cast is a 0 argument function. Even if the blx instruction were used (branch and link), the return address of the function is still only placed into a cpu register, not the stack. I really enjoy digging into the details of this kind of thing, so the discussion is very much appreciated.
@ZeroPlayerGame
@ZeroPlayerGame Год назад
@@LowByteProductions I actually went and checked, and I'm sorry to say, but libopencm3's reset handler does none such. All it does is copy the .data section into RAM, and run global constructors.
@MarvinPranajaya
@MarvinPranajaya 10 месяцев назад
Great content! It has helped me learn so much about bootloaders. Just wondering why do you not set the Stack Pointer to the APP before jumping to APP. I believe we need to do so to utilize all the RAM space? I also realized the reset handler by Libopencm3 doesnt include a Stack Pointer intialisation.
@VectorNodes
@VectorNodes 10 месяцев назад
37:36 it stands for “bull shit stuff”
@gionag
@gionag 10 месяцев назад
in linker, why don't use FILL to pad the bootloader ?
@aymaneeljahrani2280
@aymaneeljahrani2280 3 месяца назад
I’m queen on your videos !
@LaSDetta
@LaSDetta Год назад
Really nice video! I was wondering if you could use the FILL command in the linker script to ensure that the bootloader binary is always 0x8000 bytes?
@LowByteProductions
@LowByteProductions Год назад
Thanks Håkan! Yes this is definitely possible, but I think you'd need to change the semantics a little. To use fill, I think you'd need to define a memory region for the bootloader. Not a bad way of doing it at all, bit there is one advantage to the current approach that I'm not sure how to replicate using fill: its easy to wrap the bootloader.S code, and the vector_setup() function in #ifdefs, and pass a flad to the compiler like -DINCLUDE_BOOTLOADER. This way, you can conditionally include the bootloader blob in the application, or choose to omit it. Without the image, the main application would end up at 0x08000000, and no VTOR offset would be required. Not a deal breaker by any means, but something to consider.
@SumitAdep
@SumitAdep 5 месяцев назад
well explained
@MohammadShikha
@MohammadShikha Год назад
Hey, thanks for the video. I'm currently following along with the STM32F767ZI and the vector offset macro SCB_VTOR seems to require the final vector table address (0x08008000U) rather than an offsetting value (0x8000U) in order for interrupts (like SYS_TICK) to work. I'm not sure as to why this is the case, am I missing something obvious?
@LowByteProductions
@LowByteProductions Год назад
That shouldn't be the case - the VTOR is literally the "vector table offset register", i.e. it always specifies an offset. When you are moving between the bootloader and main application, you need to disable any interrupts that could occur before you're able to change the offset value. Just to check: you are using libopencm3 right? Because there is only one macro definition there, and it just points to a memory mapped io register. Edit: just checked the reference manual for cortex-m7, and indeed, the vtor specifies and offset from 0x00000000 - so yes it is effectively an absolute address. You'll have to adjust the M4 based code to account for this. I'm sure they're be other subtle detail changes too!
@twitchy9948
@twitchy9948 3 месяца назад
How did you come with this? I have exact stm32, and after setting it 0x08008000U it worked, thanks!
@saturdaysequalsyouth
@saturdaysequalsyouth Год назад
.bss is something like "block started by segment". It's probably an outdated term that was repurposed which is why it doesn't make sense.
@angryman9333
@angryman9333 Год назад
you are a genius.
@dty999
@dty999 Год назад
I'm not a C programmer, but at 25:10, why don't you let the compiler do the pointer math for you, and use reset_vector[1] instead of adding 4 to the address?
@dty999
@dty999 Год назад
Or, strictly, I guess you should redefine reset_vector as vector_table, then vector_table[1] makes more sense!
@LowByteProductions
@LowByteProductions Год назад
Definitely possible, and perhaps the better way to do it! Libopencm3 actually defines a structure for the vector table, so casting the address to a pointer of that structure, and referring to the reset vector by name would another option.
@dty999
@dty999 Год назад
Or better yet, just have something like void_fn* interrupt_table = (void_fn*)MAIN_APP_START_ADDRESS; and then you can just go interrupt_table[1](); to call it.
@stati5tik
@stati5tik 10 месяцев назад
30:30 who set the address to the reset_vector in reset_vector_entry? is this hardware specific?
@LowByteProductions
@LowByteProductions 10 месяцев назад
It's per-platform, indeed. On the STM32 Cortex-M4 chips it tends to be at 0x80000000, but another vendor might map the beginning of flash elsewhere
@viniciusgabriellinden4724
@viniciusgabriellinden4724 Год назад
why not something like `void_fn jump = (void_fn) (MAIN_APP_START_ADDRESS + sizeof(int)); return jump();`? more concise and does not depend on the bit width...
@LowByteProductions
@LowByteProductions Год назад
You're absolutely right, and I have a feeling you'll enjoy the next video in the series 😁
@ulysses_grant
@ulysses_grant 7 месяцев назад
I am a simple man. I see a random channel with a video of a guy dumping game boy cartridges and I subscribe.
@LowByteProductions
@LowByteProductions 7 месяцев назад
Me too buddy, me too.
@ulysses_grant
@ulysses_grant 7 месяцев назад
​@@LowByteProductionsJust learned about your channel. Sent the link to my brother and he just "LowByte?! This guy is a monster!" lol. Definitely subscribed!
Далее