This page aims to provide a rough guide on how to port RISC OS to new hardware. h2. Prerequisites * You have a strong knowledge of C and ARM assembler. Prior experience with the asasm/objasm assembler is advantageous. If you're planning on making heavy use of C within your HAL, make sure you've read [[Using C in assembler components]], because the requirements of the HAL can make C usage rather tricky. * You have access to all the required technical documentation for the chosen hardware platform (E.g. appropriate ARM architecture reference manual, hardware TRMs containing register maps & descriptions, circuit diagrams/etc. to help determine GPIO assignments, etc.). If not your job is a lot harder - but see [[Notes on reverse engineering]]. * You have confirmed that the chosen hardware supports the ARM instruction set, contains an MMU, and is capable of using the 32bit processor modes that were introduced with ARMv3. Thumb-only processors (e.g. ARMv7-M), or processors/hardware lacking an MMU, are not supported by RISC OS. ARMv8 processors must support AArch32 at both EL0 and EL1. * Your chosen development board has a low-level form of debug interface (e.g. serial, or JTAG if you have the necessary hardware+software) * You have a host machine that's capable of compiling a ROM image from the OS source code. This can be either a native RISC OS machine or a machine running an emulator such as RPCEmu. A copy of the "compiler":/content/sales/dde is also required. * You know how to use !Builder to make a ROM build (the [[Beginner's guide to ROM builds]] page may be useful here) * You have read the [[Hardware Abstraction Layer]] documentation * You have a lot of spare time and perseverance! h2. The not quite ten step plan # Work out how to get your code running on the target machine. On entry to a RISC OS ROM image the MMU must be off and the CPU must be in a privileged mode (typically SVC, but obviously your ROM can switch to this if necessary). # Write a small test program that does nothing other than spit characters out of your chosen debug interface (e.g. the serial port). # Make sure that your bootloader is able to run the test program, and that the test program works! # Add the test program into the RISC OS build system by creating a new product file, components file, and env file. #* For information about products, components, and env files, see the [[Developer's guide to RISC OS builds]] #** When setting up the Env file, you can pretty much just copy one from an existing ROM and modify the Build and Machine entries. See the "'adding a new machine type'":#newmachinetype section for some more information about how the machine type affects the build. #* For an idea of which modules are needed for a minimal ROM image, look at the first version of the "OMAP3 components file":/viewer/view/apache/RiscOS/BuildSys/Components/ROOL/OMAP3?rev=1.1;content-type=text%2Fplain (and corresponding "products file":/viewer/view/Products/OMAP3Dev/modules?rev=1.1;content-type=text%2Fplain). However instead of the OMAP3 HAL you'll want to use your new HAL - which for the moment will just be your test program. Also bear in mind that that file is now pretty old, so the exact requirements will have changed a bit (e.g. you'll want to make sure you're using the trunk version of the kernel instead of the HAL branch) #* To get srcbuild to find your HAL you'll have to remember to add it as a new entry to "ModuleDB":/viewer/view/apache/RiscOS/BuildSys/ModuleDB. #* You'll also need to make sure that your test program must have a makefile that provides the different rules/targets that the build system uses. For a HAL the two most important ones would be 'rom' (build the HAL) and 'install_rom' (copy the binary as '${INSTDIR}.${TARGET}'). Basing your makefile around one for an existing HAL is the recommended way of getting started. #* If you're unsure how to go about this step, see "the guide below":#newproduct, or feel free to ask on the forums - you'll be likely find someone who will be happy to make the changes for you. # Check that your test program works within the RISC OS build system/ROM image. Be aware of the [[ROM image format]] that romlinker uses, as it may interfere with any formatting that your bootloader requires. # Begin writing the HAL proper. Your aim is to get it to the point where it can call [[RISCOS_Start]] (i.e. RAM has been detected & registered with [[RISCOS_AddRAM]]). # This is the tricky bit – see if you can call RISCOS_Start and then come back out the other side at [[HAL_Init]]. There will probably be at least a couple of kernel changes that you'll need to make in order for this step to work: #* You may need to add the CPU to the list of known CPUs in Kernel.s.ARMops. #** See KnownCPUTable (for ARMv3-ARMv6), and KnownCPUTable_Fancy (for newer CPUs where the architecture field of the main ID register is set to 0xF, i.e. ARMv7+ and some ARMv6). #** You'll also need to add a new entry to KnownCPUFlags and PNameTable #* If you did have to add a new CPU, you may find that none of the existing cache/TLB control functions are appropriate. If so you'll then have to add a new set of functions to the ARMops file (a new Analyse_ function, and corresponding ARMops). #* If you're adding support for an entirely new architecture version, you might have a bigger job, as you may need to add a new MMU interface file (i.e. to be used in place of the current ARM600 or VMSAv6 file). This is a bit outside the scope of this guide, but see the "'adding a new machine type'":#newmachinetype section below. #* If things are going wrong and you don't have access to any real debugging tools (i.e. JTAG), you'll have to add some temporary debug code to the kernel, by copy & pasting relevant bits from your HAL. Things will be complicated by the fact that at some point the kernel will try enabling the MMU, thereby making inaccessible whatever hardware registers you're using for debug output (e.g. the serial port). The MMU will be turned on during the MMU_activation_zone code sequence in Kernel.s.HAL; if look just above that label then you'll see the code that sets up the initial page tables. You should be able to modify that code to map in some IO memory for your debug interface. Since RISC OS doesn't map in much memory until HAL_Init is called, chances are you can just use a logical address which matches the physical one and not have to worry about writing two sets of kernel debug code to deal with the differing MMU state. # Write code for handling the interrupt controller & timer(s), and fill in the remaining HAL entries with null entry points. This should get you to the stage the first released version of the OMAP3 HAL was at. It also means that, if you enable the debug terminal (the DebugTerminal option in Kernel.hdr.Options), and use the right set of modules (i.e. those used in the first version of the OMAP3 components file), then you should be able to boot RISC OS to the supervisor prompt and interact with it over your debugging interface ([[HAL_DebugTX]]/[[HAL_DebugRX]]). # After that, begin the long, hard process of filling in the remaining functionality and guessing what all the dependencies are for adding new modules to the ROM image (although the history for the OMAP3 components file may provide some help here) h2(#newmachinetype). Adding a new machine type RISC OS can be built to target various different "machine types". In the past the machine type has been used to target specific computers (e.g. RiscPC, Iyonix, different STB models), but now it's generally used to refer to the different CPU architecture(s) that must be supported. So if you've added a new CPU to the list of known CPUs in the kernel, you may need to add a new machine type to go with it. Specifically, if it's using a different CPU (sub) architecture, then adding a new machine type will allow the compilers to generate code which is compatible with the CPU, or takes advantages of new instructions. Or if the CPU requires a new MMU interface file to be added to the kernel (or needs other kernel changes that can't realistically be accounted for at runtime) then adding a new machine type is the way to deal with that. There are several places where the machine types are set up: * The Env files in Env.ROOL specify which machine type each product uses. * Each different machine type has its own file in Programmer.HdrSrc.hdr.Machine. * The file Programmer.HdrSrc.hdr.Machine.Machine uses the machine type to set up various build options. ** Important variables are MEMM_Type (for selecting the MMU interface the kernel uses) and NoUnaligned (for whether unaligned memory accesses will/won't be used). * The file Library.ToolOptions.APCS-32 uses the machine type to set up the default compiler flags. * A new entry will need to be added to BuildSys.ImageName.SysMap, as the machine type is used as part of the ROM image naming process. h2(#newproduct). Setting up a source tree for your new platform If I was to start a port to a new platform called Wibble, I'd add support for Wibble to the build system by performing the following steps: # Copy a suitable-looking "product folder":https://www.riscosopen.org/viewer/view/Products/ (e.g. the OMAP3Dev one) and give it the name WibbleDev # Likewise, make a copy of a suitable-looking "components file":https://www.riscosopen.org/viewer/view/apache/RiscOS/BuildSys/Components/ROOL/ and call it Wibble # Likewise, make a copy of a suitable-looking "env file":https://www.riscosopen.org/viewer/view/apache/RiscOS/Env/ROOL/ and call it Wibble. # Update the "Build setting":https://www.riscosopen.org/viewer/view/apache/RiscOS/Env/ROOL/OMAP3%2Cfeb?rev=1.5#l30 in the env file to be ROOL.Wibble (IIRC this tells Builder what components file to use) # Using the test program as the base for the Wibble HAL, I'll want to decide which of the different license folders it fits in (e.g. apache, bsd, mixed) and plonk it in xxx.RiscOS.Sources.HAL.Wibble # Edit Products.WibbleDev.modules so that instead of referencing apache/RiscOS/Sources/HAL/OMAP3 it references xxx/RiscOS/Sources/HAL/Wibble # Edit "ModuleDB":https://www.riscosopen.org/viewer/view/apache/RiscOS/BuildSys/ModuleDB?rev=1.104 to add a new entry for the Wibble HAL (i.e. base it around one of the existing HAL entries, and give it a name like HAL_Wibble) # Edit BuildSys.Components.ROOL.Wibble so that instead of using HAL_OMAP3, it uses HAL_Wibble # For the components file, env file, and moduledb, make sure to update both locations if you're working on "prepared" sources. Otherwise it either won't work or you'll have a hard time finding your changes when diffing against a clean source tree. # If Builder is already loaded, opening up its window and re-selecting the build folder should cause it to re-scan for the available environments, causing your Wibble environment to appear in the environments menu. The stuff relating the the Products file/folder is only relevant for CVS, so there's no need to do that if all you're interested in is getting code building. h2. See also * [[Developer documentation]] * [[Builder]] * [[Developer's guide to RISC OS builds]] * [[Kernel notes]]