 And welcome to today's session on embedded hardware bring up embedded software programmer perspective. As we all know embedded system are close collaboration of software and hardware. And as more and more embedded devices are coming every day, it has become important for embedded software programmer to understand the complete hardware bring up flow. In order to maybe reduce the bring up time and for faster debugging of the devices or particular IP that our engineer is working on. For example, suppose somebody knows how to read the semantic and how to find a tap point or a test point to measure some of the critical signals or clock or voltages that is really going to help. Apart from that, if you know the complete boot flow that will help to understand how what are the various components involved what are the configuration that is already done during the boot and what I need to take care when somebody is developing the device drivers at the Linux level right. So in this talk, I'm going to talk about all the steps that are involved during a hardware bring up. And what are the various topics or the area that every embedded system programmer should understand or try to gain a minimum knowledge about that and so that that will help in the further development of the system. And that will also help to squeeze the best of the power and performance of the particular device. So before I proceed, let me introduce myself. So I'm Alim Akhtar and I work for Samsung Semiconductor India R&D Center. I have over a decade experience on bring up of various hardware. My area of interest are the development of boot ROM, bootloaders, porting of Linux to a new platform. And of course, Linux device driver development. I'm one of the reviewer of UFS subsystem in Linux mainline community. So let's move forward. So this is the agenda for today. So what I have done is I have divided the complete presentation into three section. One is a pre bring up. Second is during bring up and then the last one is software components. So during pre bring up, I'm going to talk about why it is important for embedded software programmer to understand system architecture. Why it is important for a programmer to understand what are the various power clock domains? What are the external GPIs available? How we can use that? And what is the importance of understanding a semantic or how to read the semantic? And then understanding of the system memory map. And the last one is to know or to be familiar with all the debug infrastructure that is supported by the board as well as the SOC. And the second section, I'll talk about the various utilities and tools or hardware that are really helpful during the hardware bring up. And last section, which is a software component section. I'll be just taking all of you through various development involvement, a little bit on boot ROM, boot loaders, a device tree. So I'm not going to cover like what is boot ROM, what is device tree at all. I'll just touch upon this topic and as a hint that embedded software programmer should understand all these topics. And then we'll look at what are the various open source infrastructure available to build an initial root file system or RFS. And at the end we'll walk through how an OS boots on a typical SOC or a typical board. So with this agenda is mine, let's start this presentation. So understanding system architecture. So in this diagram I have depicted a very simple form of a system. So this system contains, of course, a CPU, a controller. And this controller can be any controller like DRAM controller, PCI controller or a GPU or an ISP, image processor, etc. And then we have the main bus or the bus fabric which could support like XC3, XI4, AS, or ASLite any protocol. And then it will interface with the registered state software controller through a little slower interface or bus fabric which is XI2, APB or HB converter. There's a typo here so it is HB I think. Fine, so why it is important to understand this architecture. So the first and foremost information that we get like what are the various interfaces available on this particular design. Whether it is XI4 or AS or ASLite. So that will also tell you what are the coherency level that this system supports. That also tells you what are the shareability domains that this system supports. For example, if the controller is a GPU. For example, if the controller is a GPU, then whether the GPU is in inner shareable domain or outer shareable domain with this CPU. So all this information you can get from the system architecture. The another important thing that we should look for the look in the system architecture is, let's say the controller or the IP is configured as a secure IP. Whereas your CPU is doing a non-secure transactions, right? And from a non-secure master, if you are going to access a secure IP, that transaction will not go through. It will result in a system hang or a kernel crash. So for that there will be some sideband signals provided or different SFR provided or a system register provided to configure this controller in a non-secure mode before a non-secure master or CPU can access that controller. So all those information you will get from there, right? And knowing the bus fabric or bus infrastructure will let you know what are the various QoS schemes are available that you can find to get the better performance out of the system or to identify a potential bottleneck in the system. So these are some of the things those are very critical for any system performance optimization and the system architecture understanding will let you know what are the various things. So this is some of the points that I have just listed what I just spoke about. So this understanding the system architecture will give you the big picture of the whole system. And this will also help you to understand what is the design and for what application the design is for and why, excuse me, and why this particular design is designed like that, okay? And as I already mentioned that will help you to understand what are the various sideband signals needed to take care in the programming. And this will also help you to understand what are the various secure and non-secure IPs or devices are available on the system and how to make access in secure and non-secure world. And this will also help in identifying a potential performance bottleneck if you understand the bus architecture. So this is something that all embedded system programmer should get some knowledge before going into a device driver development or any other development, okay? So the next area could be power clock and GPIO. So all devices and IOs are generally grouped into a domain. We call power domain generally based on identical voltage supplies to this device and IO. So understanding of that is really helped in implementing a low power states for the system. For example, if you have say three or four devices on the same power domain and if you're not aware of the power domain and let's say one of the device is USB and once USB is ideal, you get the USB clock, you power get it from the power management unit and then you go and turn off the actual PMIC rail, external rail, right? So what happens to the other three devices that we didn't take in care, right? So we need to understand like if all other devices are into their low power state, then we can go and cut off the external power rail to save optimal power. And this also helps to understand like when you are going to select or design external PMIC. So based on the power domain requirement, we can select what PMIC is suitable for this particular design. And this helps in effective implementation of low power state for the CPU as well as the overall system. So that's why it's very, very important to understand the various power domain. When it comes to clock, right? So clock is a basic unit of functional system. If clock is not there, nothing is going to work. So in clock, one should understand the complete clock hierarchy. So a typical hierarchy is depicted in this picture, where there's an oscillator clock, a PLL generator and then it is going to MUX and then it is that frequency is getting divided by some division factor and then it is supplied to clock IP. So this hierarchy will also tell what are the various gates available. For example, a gate clock it might be available at this point in time after divisor, a clock it might be available here. So from the MUX output, if it is going to multiple devices, you can where to get to get, which gate to apply to get that particular IP, right? So all those information will get from clock hierarchy. So it is very important to understand this. And this also helps in understanding and implementing the dynamic frequency scaling and which is going to impact your performance and functionality of the system. So the next thing is GPIO or a pin MUX or a pin control. So one of the very interesting use of GPIO is in debugging. So you know a GPIO which is connected on the board and you can program that GPIO to toggle and then you can monitor that toggling at various stage of your debugging or boot flow, right? And if any LED is connected to that GPIO, that will be really great. So you can just glow that LED and find out what happened at what stage the flow has reached. And understanding the GPIO will help you to early development of the device driver, which is connecting or interfacing to the external devices like a sensor or any sensor or a slave devices on SPI, I2C, UART, etc. Or any other external control signal. For example, if something is connected to GPS, you can easily program and develop and keep the code ready so that you can have a faster bring up time or less bring up time. Now reading the board semantics. So I believe this is one of the critical things that embedded software programmers should try to understand. So board semantics is a blueprint that help you to understand the circuitry of a specific area. Let's understand this with an example. So you are debugging one device bring up and for some reason it is not working, right? So now we are going to check the clock or the power supply to the particular device. So how to locate what are the input clocks that is going to this device or where is the probe point for the device on the board? So by looking in the semantics, we can easily find out and then we can locate on the board and try to program on the board. So for example, your device is supposed to work at 100 megahertz for some reason it is working at say 80 megahertz. So by probing you can easily find out unless you have any hardware clock out support which where you can probe and see what is the clock out coming from your SOC. So in that case, you will not be able to measure the jitter or the quality of the clock. So for that only option is to locate probe point on the board and physically measure and check the jitter etc. Similarly, your device is not getting powered on so you will try to debug from the PMI serial what was the voltage is expected and what voltage is reaching the device. So for that also understanding the semantic or reading the semantic will help you to locate the probe point and thereafter you can probe it and find that. I mean the root cause the reason for not getting the proper supply. And reading this board semantic also helps to know how the power from the PMIC is routed and what are the various critical rails available on the board. Sorry, on the board for the measurement of critical voltages. And next is to understand the system memory map. So system memory map will give you the complete memory mapping of the system, which includes where your IROM reside and what is the size of IROM and similarly like what is the size of SRAM. So knowing this, these information are required for initial programming or development of say boot ROM or a bootloader. So these are the areas that will be utilized for the initial boot. And then where is the peripherals located and the peripherals area will tell you like where are each peripherals like UART or SPI or UFS are located what are the base address for that and what are the size for those devices. And then which areas that external device can access and what is the base address of a DRAM and what is the size of a DRAM available for this particular system. And what are the memory reserved for the system uses. When I say system uses, suppose you are working with ARM Cortex MCD CPUs. So they have system registers, for example, the MPU or the NV controller internal to the CPU memory rate. So those are reserved for system uses. So this will give you a very good understanding of what area is out of range, what area is within range. For example, you have program peripheral, which is going beyond the mentioned size or address. You will come to know like, okay, you will get some exception or invalid address. And that way, excuse me. So that way you will identify, okay, something went wrong during the programming of these register sets. Fine. Yeah, so the last topic on pre-bringer phase is debugger or a GTAC. So this is a protocol for debugging. And one should at least know one of the hardware debugger, how to use it and how to connect it and all about how to debug the code step by step. So either a lot of actress 32 or address streamer or anything equivalent to these devices. These devices are very, very useful, especially when it's come to low level firmware debugging or boot loader debugging or Iron debugging. And suppose you got a bare board, you have program everything and now you pour on the board and nothing boots. Right. So what are the ways to debug. So the only ways remaining is to connect the debugger and try to find out if the CPU was out of reset or not. Especially in case of boot ROM, it is very much to know how to use this hardware debuggers. Otherwise, there is no other options to really debug and root cause what is happening inside the silicon. Okay. So with that, let's move to the second section, which is during bring up. What all things we need to understand and with an embedded software programmer should know. Right. So very first thing is a flash programmer. So suppose you got a board. So the board with a new fab out silicon and this silicon is having only boot ROM flash onto the iron, which is a read only memory again. So power on the board. Once you power on the board, the boot ROM will boot. But since the size of the boot ROM is limited, we cannot put everything in the boot ROM. Right. So it will look for the next stage of boot loader into external storage device. So external storage device could be anything which is listed here like a QSPY flash or SPY flash or your SD card or MMC flash. It is a USB boot if USB boot is supported or it's look for the images boot images onto the network so that you can do a network boot. So we need those external flashers or flash programmer to program these flash devices beforehand. Right. So once the board is there, you can if the flash is on board, then you can connect those flash programmer on the board and you can program through the host machine. You can connect the SD or USB drive. Sorry. USB drive. You can just directly connect to the host machine and you can just copy the bootable images there and let the boot ROM decide which boot image to select and then goes on. Okay. So the next important things start with the debugging. The system has started booting and it has stuck somewhere. So how to proceed? So one way is to have LED gluing at particular important initialization. For example, you did a clock initialization or a GPU initialization or a PMIC initialization, etc. Or say any controller initialization device initialization. So you just keep gluing LED and saying that that will indicate. Okay. The code flow has reached this particular time. For this particular point or connect a hardware debugger and then step into your code step by step debugging and find out. Okay. At what point the system is hanging or it is not proceeding further. Right. Another way is to log stage into some of the spare SFR if it is available on the system and read those SFR using either a debugger or any other available mean. Right. And the next one debugging point will be print the output on the console so that we can see what is happening or what all things are coming. Right. And and you should have or one design should have something like if the primary boot fails, then what are the ways to put the device into a recovery mode so that we can put the device into recovery mode. And then you can download the recovery images and start putting those recovery images. So this is on the debugging side and the next equipment that is very useful is oscilloscope. So as I told you one example right you are debugging some devices and something is not working. Now you want to check what is the clock? What is the frequency? Whether the clock is clean or it's a clock is jittery. So all those you can capture it on the oscilloscope and analyze the data. So what an embedded system programming should know so they should be aware of how to set a basic trigger type and trigger level. And how to measure the biggest clock or power and how to read the same on the oscilloscope screen. And for a small protocol debugging like you are debugging SPI or I2C then you captured a sample for some duration and analyze the data. For example, if you are debugging I2C then see what are the slave address it was sent, what was the act, when was the MAC. All those things can be easily debug using oscilloscope. Similar to oscilloscope there is another device called logic analyzer. So this is generally used to analyze little complex protocols. Like for example, if you are debugging a DRAM data transfer, you can easily captured all the data line and address line and then see for what address what data was transferred and whether it is expected data or valid data address stop is going or not. And various other bus protocol you can analyze using it. So here also the basic setups, how to configure the device, the logic analyzer, how to capture so all this information one should know or try to understand or try to gain that knowledge. So this one is a very simple and very important device, digital multimeter that will give a quick measure of voltages current and temperature around a particular device or SOC and very, very handy. So one should know like how to handle a multimeter and how to carefully probe on the board. So probe point you will get from the semantic and then using multimeter we can easily find out what are the voltage and currents going for a particular device or an IP. Okay. So with this, let's move to the last section, which is software components. So first thing is development environment. So, first thing we need a development machine. And we need a native compiler or a cross compiler. For example, if you are developing software for architecture or on CPUs, and you are using x86 machine, then you need on compilers and similarly for that is to be in case you are developing software or driver for the native system then you need a GCC compiler. And then we need a good source code editor you can use any anyone that you are comfortable in. And of course source code explorer like a C scope or graphical version case scope, etc. And host debugger software. For example, if you're using a lot of back trace 32, then it's come with a whole software. So understand the tools. What are the various options available. How you can do a step by step debugging how you can load the symbol. How you can look for a particular function. How you can set a breakpoint. And how you can set a software breakpoint as well as hardware breakpoint. So all those information you can understand from the host debugger software. So let's talk about a little bit on boot ROM. So as we all know boot ROM is the first piece of code that gets executed after the SOC is powered on. So as soon as the SOC is out of reset it will jump to a predefined location in most of the system it is generally 0x0. Sorry. Excuse me. So in most of the system it is 0x0 and it's a look for a code there and the boot ROM is already fused in a read only memory. So it's start that execution. So what an embedded software programmer should be aware of. Like what all the things are getting initialized in boot ROM. So generally boot ROM developers are different team altogether. It might not be the same team as a device driver development. So connect with them and try to understand what are the things getting initialized. So in common in general we initialize like a clock basic clock setups some of the GPI setups and if required PMIC setups and one of the external storage initialization. Then one should understand what are the various secure and non secure boot path. And something I have not mentioned here we should understand what are the various low power states. So how to resume a system. So for example if you're implementing suspend and resume so you must understand. During suspend what is the role of a boot ROM and during resume what is the role of a boot ROM and what are the various condition for a secondary boot device so how boot ROM will move to secondary boot device from a primary boot device. So these are some of the basic things that one should try to understand and get knowledge about for that particular system. So once boot ROM has booted so it's look for the next stage of boot loader. So there is there comes the boot loader. So boot loaders naming convention can be depends on each developer or each development team like some people call is a BL1, BL2, BL3 which is indicator of boot loader 1, BL2, BL3 if you're going to call boot ROM as boot loader 0 or BL0. So here also very sister programmers will try to understand what is the flow. What are all things are getting initialized what is the secure non secure path how you can control a PMIC what are the various control or option provided in the PMIC. And how to download images to the DRAM and how the control is transferred or when the control is transferred to the latest kernel. And some of the peripherals like extra peripherals gets initialized at boot loader stages. For example if you want to initialize a display for a splash screen or something like that. Or you want to initialize an audio to get some early sound or a startup song etc. So the boot ROM is booted the boot loader is booted now next is a device tree. So as we all know device tree is a data structure that described the hardware. And mainly device tree supports a wide range of hardware with a single kernel image. And Linux uses device tree data for three major purpose one is for platform identification. Another is for runtime configuration and the third one is for device population. Or device platform device driver data population. So let's take a simple look on the one of the device tree nodes. So this is an example of I2C node. So you can see there's a compatible field. So using this compatible string it is going to match to a driver or binder driver. And then there are address sales, size, sale and rich property. And then there's a I2C slave device which is a child node of I2C master device. So in this example it is an RTC device with slave address is 58. And the compatible name is mentioned here. So using this compatible it's going to discover the driver suitable driver and then bind the device with the driver. And then there is property for the slave node. So I'm not covering the kernel part because as you all know right you can configure the kernel where you can select various options. You can select the particular SOC or the platform from the menu config or the xconfig. And then you can build the image along with the device tree. So the next thing is a root file system. So there are good infrastructure already provided by open source. Community like build root or Yocto project or build or a RAM disk. You can build your own RAM disk. So I've given this link you can just go through and it's super easy to use build root or Yocto project for development of the initial root file system. So let's move on. Before we see how an OS boots or what is the complete boot process for a silicon or a board. Let's try to understand what are the various booting stages involved when we are going to boot an operating system. So typically these stages can be multiple stage as well. So I just try to put a generic stage here where I have put stage one as boot ROM or called BL0. So boot ROM will boot from ROM which is a read only memory. And the stage two is BL1 or the first stage of the bootloader. And most likely that is going to boot from SRAM or a TCM or similar tightly coupled memory. The next stage of boot loader boots from DRAM because your BL1 might have initialized the DRAM for the larger image to be downloaded and executed. Next stage is a kernel and DTB file device tree block. And the last stage could be booting a rich OS like Android Ubuntu or any other small root file system. So as you can see in this diagram, so left hand side is the SOC which has internal SRAM. The middle one is an external storage device. It could be EMC, UFS or a QSPI flash or any other flash. And the right side diagram is a DRAM, a system DRAM. So what happens once we power on the system to power on the CPU, it starts executing at the boot ROM. And boot ROM initializes one of these external storage. And at the end of the boot ROM, it will try to copy the next stage of boot loader into the internal SRAM. And then for example, it has copied BL1 or BL2, BL1 and BL2. And somewhere in BL1 and BL2, a DRAM controller is initialized and DRAM trainings are performed so that DRAM is ready to download for a larger size image. And then the next stage boot loader will copy the kernel image or the device tree block into the DRAM. And the OS image or a root file system into the DRAM. And then the last stage of the boot loader will pass the control to the kernel. And then kernel will start executing, it will pass the DTB and it will populate all the platform devices and all the initialization in the kernel. And lastly, it will just mount to the root file system. And that will give you a kernel prompt where an application is ready to run on that system. So these are some of the references I have provided here for the diagram that I have used in presentation and for the RFS, I already give the link in that particular slide so you can just go through it and see, get more information out of it. So that's all for today's presentation. Hopefully this will help you to understand a typical hardware bring up process and a complete boot flow. Thank you and have a nice day.