Bare metal embedded lecture-4: Writing linker scripts and section placement

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this lecture let us understand about linker scripts first of all let's learn what exactly is a linker script linker script is a text file which explains how different sections of the object files should be merged to create an output file linker and locator combination assigns unique absolute addresses to different sections of the output files by referring to the address information mentioned in the linker script linker script also includes the code and data memory address and size information so inside the linker script you have to mention the various memories which are present on your target board and also you have to mention the size and address information linka scripts are written using a new linker command language and GNU linker script has the file extension of dot LD you must supply linker script at the linking face to the linker using - T option we'll see that when we run the command to write a linker script you have to first understand different commands used to explain various things in the linker script there are commands like entry memory sections keep a line and at I mean there are many commands but I have just listed here some of the important commands first let's explore about the entry command this command you have to use to set the entry point address information in the header of final year left file generated what this command does is it just a populate entry point address information in the LF file header that's it in our case reset handler is the entry point into the application because that is the first piece of code that executes right after the processor reset isn't it the debugger uses this information to locate the first function to execute this is actually not a mandatory command to use but this is required when you debug the e.l.f file using the debugger such as gdb this is given just for the debugger say strictly speaking it is not required this is how you should use the entry command entry and in the parenthesis you have to give the symbol name that is the function name which is an entry point into your application in our case we are going to write something like this entry reset handler where this at handler is a function name or you can also call that symbol let's use the entry command and let me get back to this memory come on let's head over to my workspace and let's create one linker script here you have to give the file extension dot LD but let me open my come on front here I'm going to create one linker script let me call it as stm32 LS a linker script and I'm going to give the extension dot LD here it is let me open this file first let's use the entry command you can use the entry command so make sure that all our capital letters after that open the parentheses and here you have to give the a symbol name symbol name is you have to refer to your startup code here this is our entry point let's copy this function name and paste here that's it there is no semicolon here you should not give any semicolon this will set the entry point address in the final e.l.f which you are going to generate next let's explore about the memory command this command allows you to describe the different memories present in the target and start address and size information the linker uses information mentioned in this command to assign addresses to merge sections that is what we call as relocation our sections must be relocated to different addresses that is done by the address what you mentioned in the linker script by using the memory command the information is given under this command also helps the linker to calculate the core and data memory consumed so far by the application and throw an error message if data code heap or stack areas cannot fit into our level size by using memory command you can fine tune various memories available in your target and allow different sections to occupy different memory area typically one linker script has one memory command so you will generally find only one memory command inside a linker script let's see the syntax of memory command you had to use the name memory here that's a command name which must be in capital letters then you have to do the body of that come on and inside the body you can write many statements in this format the memory statement has three parts this is a label this is a worry gene comma Lent a label will have its own attribute attribute list a tribute if used it is optional actually but if used you have to give that in the parentheses label : origin and comma length let's understand what exactly the label label defines name of the memory region it is just a label or a user-defined name given to a particular memory region this name will be later referenced by other parts of the linker script by using this statement you just give a name for a memory region which is present in your target and after that using this very gene name this is a standard key word of the linker you have to use exactly like this using this name you have to mention the worry gene address or the start address of that memory region that's why this defines religion address of the memory region after that you have to mention the length information defines the length information of the memory region again you have to use the standard name length here length is equal to you have to mention the size here don't worry when we see the example it will get cleared memory command may have multiple such statements let's move forward let's talk about this attribute this defines the attribute list of the memory region valid attribute list must be made up of these characters which are mentioned in this table if you mention are here then that means read only Section W means read and write sections X means sections containing executable code like that you can mention these attributes either in capital letters or in small letters and you can also combine two or more attribute letters so we'll see that when we do an exercise let's move forward let's take an example of our microcontroller stm32f4 VD t6 which has 1 MB of flash size and it has s Ram one of 112 kilobytes and sram2 of 16 kilobytes let's see how we can write a memory command for this let's type the command memory and then give the body by using these curly brackets after that let's define our level memory regions of our target in our target our 3 memory regions are available flash sram1 and sram2 first let's explain the first memory region first give the label for the memory region let me call that code memory or you can also call it as Rob or you can also call it as flash so any name you wish you can give I will just use flash and attribute list you have to give in the parentheses I would give a readable and executable because flash memory contains code isn't it that is not writable by the user program that's why I would vomit w here I would just use read end executable : let's write the origin for that you have to use the standard name origin is equal to what is the original flash 0 cross 0 8 0 0 0 0 0 0 comma length is equal 2024 kilobytes for the kilobytes you can write k that will be expanded to number of kilobytes or you have to mention after multiplying with a thousand 24 years otherwise just mentioned k here so that is a correct syntax no problem and after that let's explain the sram1 sram1 you can read write execute you can even execute code from s wrap origin is equal to 0 cross 2 0 0 0 0 0 0 0 and length is equal to 160 k as ram 2 again attribute i can use RW x origin is equal to here you can use so what is the origin of s ramp to the end of SRAM 1 is nothing but origin of SRAM 2 and you can calculate something like this you can copy this here plus this 116 K minus 4 year today this is the origin or you can calculate the final value and you can write it after that length is equal to 16 K if you have more memories in your microcontroller than you can mention them only if you have any plan to use them in the linker script otherwise need not to mention for example backup SRAM so this microcontroller also has backup a strap that you can explain here and if your microcontroller has CCM memory and if you have any plan to use that by using the linker script then you can explain the CCM memory and various other things for our example we only want to use SRAM and the flash that's why I would just Club this sram1 and sram2 to just make it as SRAM I would not need these two segregations here since in this example we are just using flash as our ROM and SRAM as our readwrite memory I would just use two statements here I would just consider SRAM 1 & 2 as whole SRAM that's why I would just write SRAM here and I would just write it 128k your memory come on which explains two memory regions one is code memory that is this one and another one is data memory which is estra so let's explore about sections command sections command is used to create different output sections in the final e.l.f generated this is an important command by which you can instruct the linker how to merge the input sections to ield an outer section this command also controls the order in which different output sections appear in the final LF file generated by using this command you also mention the placement of a section in a memory region for example you can instruct the linker to place the dot text section in the flash memory region which is described by the memory command let's see one example of sections command or to use this command so it all starts with the command keyword section this is a standard keywords you have to write in all capital letters and after that this is a body factions command is used to create different number of output sections in the output file for example in this case the output file generated will contain two sections one is dot text section and another one is dot data section this command instruct the linker to create two sections in the final output file generated in this case the output file is nothing but dot e.l.f file the sections will appear exactly in this order first dot text section will appear followed by dot data section let's take this example this is one of the output section which we want to create here this is a label of the output section this label can be anything it depends on you you can give any name you want but you have to follow some standard naming convention this is the output section name this is a body and this gives the address information to the linker and the locator where to place this section in the memory this is a combination of VMA and LMA where element stands for load memory address and VMA stands for virtual memory address and more on that we'll see later how to use the syntax property but this actually gives the section placement information in the memory this output section is used to merge all other sections of individual input files how many input files will have got in your project so we have got three input files isn't it main dot o any d dot o and we have one more start up daughter as I described in the earlier slides and each object file contains its own different sections like text data BSS constant by using this output section we are going to merge all sections of input files like this let's use this text section to merge all is our vector section of all input files merge all dot text section of all input files and merge all dot ro data section of all input files after that just mentioned our dressier where those sections should go and after that let's use another output section dot data to merge our data section of all in files let's edit our linker script to create some output sections I'm going to write sections here and I'm going to open the brackets the first output section what I want to see in the output PLF generated is at the dot txt this is the name of the output section or label you have to give : and its body here let's merge text section of Maine dotto early dotto and startup daughter how do you write this you can use one shorthand notation so you can mention something like this you can use dot txt of all input files you can use the wild-card character e of stock asterisk you can use this denotes consider dot txt of all input files instead of writing dot txt of Maine dot o LD dot Oh Charlotte oh you can use this shorter notation if you again refer to this diagram this explains storage of final executable in code memory the initial code space must contain the vector table after that only the dot tex action should appear we have to follow this order otherwise our application will not work properly that's why what you have to do is you have to first merge the dot is our underscore vector section dot is our underscore vector of all input files you can use wildcard character for this application it is not required because there is only one is our vector section but that's okay this is a generic statement after that according to our diagram we want to place dot Auto data let's do that star off dot our Oh ditto this output section comprises of all these individual files section we just created one output section that is dot txt now you have to decide where you wish to store this section in the memory that means you have to mention a two memory regions for this section one is VMA and another one is LM a where we ma stands for virtual memory address and LM a stands for load memories before that you have to ask one question so do you relocate this section in your startup code no we don't relocate this this is going to be stored in the wrong space ROM in our cases flash it doesn't have any relocatable address that means VMA and LMA are saved for this section that is flash this section should go to flash and flash begins from here that's why next step is you have to mention the section placement by using the symbol greater than what you do is give a greater than symbol and here you have to mention the VMA then use the command at greater than symbol give space and now mention the LMA we MA in this case is flash and LM a is also flash once the linker sees this what it does is it generates absolute addresses for this section and that address is fall in the memory region what you mentioned in the VMA after that the linker also generates load addresses for this section that addresses fall in this memory region what you mentioned after the at command don't worry so again when we disassemble the final executable by using disassembly tool you can understand more in this case both VMA and LMA are sale you need not to write something like this you can just omit this so you can just mention like this this means that we am a and LM a are safe let's create the next section the odd data and again I'm going to merge data sections of all the input files here the dot data section is relocatable isn't it this must be stored in flash but the startup code has to copy this section from flash to SRAM that's why the load address is fixed that is flash in the flash first this section will appear and right up to that this section will appear that's why you have to mention load address as flash whatever the VMA and the VMA in this case is Ezra when linker sees this so it will generate load address for this section which falls in flash right after this section but the absolute address of this section will fall in the memory region SRAM which starts from this memory location I will show you practically so when we disassemble the code that's it we created two sections this is for initialized data what about uninitialized data that we call as VSS let's create one more section BSS and again this is nothing but collection of all individual BSS sections of different input files and as I said this will not get stored in the flash that's why it has only we MA so it doesn't have any l ma we ma is nothing but Ezra we just created a linker script which can generate 3 output sections for the final executable and we have to keep improving this linker script this is not final in the next lecture we will explore one more important concept of the linker script that is location counter now we created our linker script according to this memory layout and the data section which is stored in the flash needs to be relocated by the startup code but to relocate this section you need couple of information at least you should know the boundary Val ro data ends where this section ends so you should know this information and after that you should also know the size or if you know the beginning address or if you know the ending address of our data section and if you know the ending address off dot data then you can calculate the size you can use this information in the C startup code to relocate the section otherwise you can't do it isn't it now the question is how do you trace such boundary information in your C program the answer to that question is the boundaries can be tracked inside the linker script and after that that boundary information can be passed to the C program for that the linker gives you one nice feature called location counter this is a special link a symbol denoted by a dot location counter is denoted by a dot this symbol is called location counter because linker automatically updates this symbol with location information you can use the symbol inside the linker script to track and define boundaries of various sections you can also set location counter to any specific value while writing linker script location counter should appear only inside the sections command you have to remember that so you cannot use that outside the sections command that would throw you linker error the location counter is implemented by the size of the output section that helps you to track the boundary let's make use of location counter in our linker script before that we had to explore one more thing that is linker script symbols creating linker script symbols we use location counter symbols with other linker script symbols let's explore about the linker script symbol in the next lecture in this lecture let's understand about linker script symbol and later we can understand how to use the location counter and linker script symbols together what exactly the symbol a symbol is the name of an address or memory location symbol declaration is not equivalent to a variable declaration what you do in your C application for example consider a tea program let's say main door see and let's say you have this statement what is this this is a variable definition here your goal is to store a value hundred into some memory location basically this is a global variable if it is a global variable then it will go into that HR memory but you don't know the location if you want to modify the value of this variable then you just do this here you don't know the location where you are going to keep this value 50 you just write by using the variable name but at the background it must be converted into an address manipulation at the end of the day everything is addressed so the value 50 must go to some addresses endures in this case some memory location must be modified to put the value 50 the question is how this variable name is replaced by the address that happens because of the symbol table when you compile this program may not see you know that it will get converted into main dot oh and in the main dot oh the compiler maintains a table called symbol table for the compiler this is not a variable name it's a variable name for you for the programmer for the compiler or linker terminology we call it as a symbol name it's a symbol name a symbol is the name given for an address the symbol table majorly maintains two columns one is address and another one is symbol name here you can see that there are two symbols one is this one that's a variable name my value and it has its corresponding address when you do this that means here you are trying to modify an address for you you are trying to modify variable but at the background you are trying to modify an address so the address will be resolved by looking into the symbol table which is maintained by the compiler in the object file if you consider this function definition here this is a function name from one basically the function definition belongs to the text section restored in the code memory this is also maintained in the symbol table here this is a symbol name from one is a symbol name and this is the Associated address of that function in the code memory like that every object file are maintains the symbols and its associated addresses please remember that in your C program you don't write symbol what you do you do variable definition you do variable declaration you do function definition so you don't create any symbols in the C program symbols are created and maintained by the compiler that's why we never worry about creating symbols in the C program now the scenario is different not worry about creating some symbols because we are writing the linker script and inside the linker script we want to catch these boundary information how do you store the boundary information so would you create variables no you can't because we are not writing any dot C file which is going to be compiled by the C compiler isn't it we are writing linker script which is just a text file which is going to be passed by the linker that's why we cannot create in variables to catch or store the boundary information and other things that's why we have to create some symbols that's what we call as linker script symbols take a look into this example so here I have created a couple of symbols symbols is written exactly the same way how you write variable definition for example consider this please note that this is symbol definition or symbol declaration this is not a variable what is symbol a symbol is the name given for an address this is the value of the symbol when linker sees this because compiler will not see this why because it is in the linker script linker script will be passed to the build system during linking stage integer linker is going to see this when linker sees this entry it is going to add this entry to the symbol table of the final executable that's it symbol name and its associated value like this this is also one more symbol declaration here you can see that I have created one more symbol to catch the end of text section here the symbol ladies end of text and that is is equal to the dot operator that is the location counter remember what I said in the location counter explanation let me open that the location counter is incremented by the size of the output section this will happen automatically by the linker at the beginning location counter is equal to the VMA that is assumed by the linker that means dot is equal to initially disorders zero cross 0 8 0 0 0 0 0 0 here location counter value will be incremented by the size of the text section that's why this symbol will now hold the end of text section the address of end of text section you get the boundary now you can export this symbol to the C program and you can access the exact address where the text section ends so we'll see that later similarly you can create any number of for linker script symbols and you can store some value here and you can access that from the C program we will create some more linker script symbols to catch the boundaries of different sections with that note I would like to end this lecture and in the next lecture let's edit our linker script to create some symbols in this lecture let's edit our linker script to create some symbols let's refer to this diagram to catch some boundary addresses first of all in this diagram so this is a place where the text section ends this is the beginning of data section in the wrong we should know this address if we know this address then from this address we can start copying from flash to SRAM and we should also know the start address in the data memory this is the source address and this is the destination address we should know both source and destination addresses after that we should know the size of this data section that is how many bytes of data we want to copy from code memory to data memory we at least need all these three information let's create some symbols to store these values let's get into the linker script and let's create one symbol you have to select some meaningful symbol name now the rules what you follow to write a meaningful and legal variable name the same rules you can follow to write a symbol name let me create one symbol name underscore etext that is end of text and I equate this to the location counter the dot operator remember that this symbol declaration must be terminated with a semicolon what did I do here I stored the value of location counter into a symbol name underscore e text as I said in the previous video or this location counter symbol will contain the updated address information of this text section this is end of text isn't it and after that so here let me create some more symbols as data start of data is equal to the location counter you have to remember this location counter always tracks VMA not LM a location counter always tracks VMA that's why at this point the location counter value is nothing but start off we are May which is nothing but has from address that is nothing but this one that we get one more linker script symbol end data is equal to location counter here the location counter value will be updated by this much size this is a text this is s data this is e data if I do idiot R minus s data I would get the size this is a source this is a destination I can derive all other information let's create some linker script symbols for BSS section so I will call this as underscore start BSS is equal to the location counter and here I can create one more symbol ebsf is equal to location counter we almost finished writing our linker script and in the next lecture let's use this linker script to link our project to create final executable complete up to here and we'll explore about linking in the next lecture
Info
Channel: Fastbit Embedded Brain Academy
Views: 31,222
Rating: undefined out of 5
Keywords: arm cortex, cortex m4, arm embedded, bare metal embedded, embedded systems tutorial, stm32 tutorial, arm programming tutorial, keil programming, stm32cube, microcontroller, microcontroller programming, embedded software, stm32 discovery board, cross toolchain, build process, embedded projects, stm32, object file, makefile, linker script, linker script command, linker script from scratch
Id: B7oKdUvRhQQ
Channel Id: undefined
Length: 37min 40sec (2260 seconds)
Published: Sat Apr 25 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.