https://wiki.emacinc.com/api.php?action=feedcontributions&user=Tstratman&feedformat=atomwiki.emacinc.com - User contributions [en]2024-03-28T20:57:19ZUser contributionsMediaWiki 1.31.6https://wiki.emacinc.com/index.php?title=Xenomai&diff=4881Xenomai2015-10-28T07:02:18Z<p>Tstratman: added detail to development services, changed status to review</p>
<hr />
<div>{{todo| Review (10.06.2015-13:07->MW+);(10.28.2015-01:22->TS+);(10.28.2015-02:00->TS+)|Michael Welling| project=OE 5.0,MW,TS }}<br />
{{#seo:<br />
|title=Xenomai<br />
|titlemode=append<br />
|keywords=<br />
|description=About Xenomai<br />
}}<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /**************************************** Page Description Text ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
<br />
__TOC__<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** Background Information ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:bg | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
Xenomai is a real-time operating system (RTOS) framework designed to work alongside Linux by providing several APIs for developing and running real-time applications on Linux. Xenomai can be used to add a hard real-time performance to a Linux system, operating under the limits of the hardware. The Xenomai design allows for native applications to run side-by-side with real-time applications on the same target hardware. It can also provide a migration path from a proprietary RTOS such as VxWorks, pSOS, VRTX, or uITRON to an embedded Linux environment through the use of skins providing the required APIs. <br />
<br />
Xenomai has a mature code base that is under active development tracing back to 2001, and is designed to run on many different target architectures including x86, ARM, Blackfin and NIOS2.<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** General Information *****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:geninfo | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
=== Xenomai 2 ===<br />
<br />
Xenomai 2 was the previous Xenomai development version at the time of this writing. It was developed for around 10 years before the development of Xenomai 3. Xenomai 2 is a dual-kernel-only system design, where the real-time Xenomai core runs alongside the Linux kernel and handles all time-critical tasks. The mechanism for this operation is provided through the ''Interrupt Pipeline'' (I-Pipe). The real-time co-kernel runs at a higher priority than all Linux tasks, only allowing Linux to run when no real-time tasks require execution and preempting Linux tasks as needed.<br />
<br />
Xenomai plans official maintenance of the Xenomai 2 branch through January of 2016.<br />
<br />
=== Xenomai 3 ===<br />
<br />
Xenomai 3 was a significant new development for the Xenomai platform. Driven by the goals of increased flexibility and improved system design and enabled by the increasing level of support and development of the native Linux PREEMPT_RT patchset, a single-kernel option was introduced (code named Mercury) while maintaining support for the traditional dual-kernel configuration (code named Cobalt).<br />
<br />
==== Cobalt core ====<br />
The Cobalt core configuration is the traditional co-kernel configuration and is the evolution of the Xenomai 2 architecture.<br />
The Linux kernel is patched to allow the Cobalt core to deal with real-time activities including interrupts and scheduling.<br />
The RTOS APIs provide an interface to the Cobalt core from user-space. The co-kernel configuration relies on the Adeos I-pipe<br />
patch for the sharing hardware resources between the kernels. EMAC uses the Cobalt configuration by default as it more closely<br />
matches our existing Xenomai 2 product orderings and typically offers higher performance and more flexibility for both hardware and software support.<br />
<br />
==== Mercury core ====<br />
The Mercury core is a single kernel configuration that relies on the Linux kernel for the real-time capabilities. Typically this requires PREEMPT-RT support to be enabled in the kernel to meet timing requirements. The non-POSIX real-times APIs are emulated over a native threading library preferably NPTL. The Mercury configuration currently requires no Xenomai-specific kernel features but the kernel should provide CONFIG_HIGH_RES_TIMERS and PREEMPT-RT for bounded latencies.<br />
<br />
=== Licensing ===<br />
The Xenomai kernel space is licensed under GPL v2 and the user-space libraries are licensed LGPL v2.1.<br />
<br />
== EMAC Xenomai Package ==<br />
Xenomai provides several device drivers and user-space utilities in it's distribution. The device drivers rely on the Real Time Driver Model (RTDM) skin. Xenomai provides real-time drivers for CAN, serial, IPC, networking, data acquisition, and testing using the RTDM. These drivers can be used as a reference when creating drivers for new devices.<br />
<br />
The user-space utilities and examples are used to benchmark the target system and demonstrate the API for the RTDM drivers.<br />
<br />
The standard EMAC Xenomai package provides the basic Xenomai build for the desired target. This includes the kernel, filesystem, and SDK add-ons to start Xenomai development.<br />
<br />
=== Standard Features ===<br />
<br />
The EMAC Xenomai base package's features include:<br />
* Pre-installed Xenomai kernel and filesystem utilities<br />
* SDK add-on for Xenomai development<br />
* Basic Alchemy timer example<br />
<br />
<br />
The EMAC Xenomai package supports real-time features including:<br />
* RTDM including real-time interrupts and driver API<br />
* Timers<br />
* Real-time UART Serial (HW Dependent)<br />
* Real-time GPIO (HW Dependent)<br />
<br />
=== Additional Features ===<br />
Additional packages include:<br />
* Real-time CAN (HW Dependent)<br />
* Real-time SPI (HW Dependent)<br />
<br />
<br />
== Development Services ==<br />
<br />
EMAC has extensive experience developing and supporting Xenomai builds for a wide range of hardware platforms including ARM, x86, Blackfin, and others. Customers rely on this service to offload the core real-time system implementation and testing so that they can more rapidly focus on their application development. EMAC can provide real-time board-support packages, driver development, and application development. <br />
<br />
In one particular instance, a customer required a custom hardware design with software support for hard real-time latencies on several communications interfaces, including CAN Bus, RS-485, and SPI. EMAC used a standard Xenomai build for the target processor and developed drivers for the USART controller and SPI controller in the processor. While the customer began application development and testing, EMAC expanded the real-time BSP to support an SPI-based CAN controller using the newly-developed RTDM SPI driver. EMAC then worked directly with a customer-contracted engineering firm to support compliance with a required communications protocol stack. This development service took the burden off of the customer for many of the complex real-time tasks and allowed them to focus on developing a highly-specialized application to deliver a market-leading product.<br />
<br />
For more information on EMAC's development services and to discuss your real-time requirements contact sales: http://emacinc.com/ordering-information<br />
<br />
== Further Information ==<br />
* [[Example_Xenomai_Timer|Example Xenomai Timer]]<br />
* [[Using_Xenomai_with_the_EMAC_OE_SDK|Using Xenomai with the EMAC OE SDK]]<br />
<br />
=== External Links ===<br />
* https://xenomai.org/start-here/<br />
* https://xenomai.org/introducing-xenomai-3/<br />
* https://xenomai.org//documentation/xenomai-3/html/xeno3prm/<br />
* https://en.wikipedia.org/wiki/Adaptive_Domain_Environment_for_Operating_Systems<br />
* https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Xenomai&diff=4880Xenomai2015-10-28T06:32:06Z<p>Tstratman: added detail to cobalt core</p>
<hr />
<div>{{todo| InProgress (10.06.2015-13:07->MW+);(10.28.2015-01:22->TS+)|Michael Welling| project=OE 5.0,MW,TS }}<br />
{{#seo:<br />
|title=Xenomai<br />
|titlemode=append<br />
|keywords=<br />
|description=About Xenomai<br />
}}<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /**************************************** Page Description Text ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
<br />
__TOC__<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** Background Information ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:bg | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
Xenomai is a real-time operating system (RTOS) framework designed to work alongside Linux by providing several APIs for developing and running real-time applications on Linux. Xenomai can be used to add a hard real-time performance to a Linux system, operating under the limits of the hardware. The Xenomai design allows for native applications to run side-by-side with real-time applications on the same target hardware. It can also provide a migration path from a proprietary RTOS such as VxWorks, pSOS, VRTX, or uITRON to an embedded Linux environment through the use of skins providing the required APIs. <br />
<br />
Xenomai has a mature code base that is under active development tracing back to 2001, and is designed to run on many different target architectures including x86, ARM, Blackfin and NIOS2.<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** General Information *****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:geninfo | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
=== Xenomai 2 ===<br />
<br />
Xenomai 2 was the previous Xenomai development version at the time of this writing. It was developed for around 10 years before the development of Xenomai 3. Xenomai 2 is a dual-kernel-only system design, where the real-time Xenomai core runs alongside the Linux kernel and handles all time-critical tasks. The mechanism for this operation is provided through the ''Interrupt Pipeline'' (I-Pipe). The real-time co-kernel runs at a higher priority than all Linux tasks, only allowing Linux to run when no real-time tasks require execution and preempting Linux tasks as needed.<br />
<br />
Xenomai plans official maintenance of the Xenomai 2 branch through January of 2016.<br />
<br />
=== Xenomai 3 ===<br />
<br />
Xenomai 3 was a significant new development for the Xenomai platform. Driven by the goals of increased flexibility and improved system design and enabled by the increasing level of support and development of the native Linux PREEMPT_RT patchset, a single-kernel option was introduced (code named Mercury) while maintaining support for the traditional dual-kernel configuration (code named Cobalt).<br />
<br />
==== Cobalt core ====<br />
The Cobalt core configuration is the traditional co-kernel configuration and is the evolution of the Xenomai 2 architecture.<br />
The Linux kernel is patched to allow the Cobalt core to deal with real-time activities including interrupts and scheduling.<br />
The RTOS APIs provide an interface to the Cobalt core from user-space. The co-kernel configuration relies on the Adeos I-pipe<br />
patch for the sharing hardware resources between the kernels. EMAC uses the Cobalt configuration by default as it more closely<br />
matches our legacy Xenomai 2.x product orderings and typically offers higher performance and more flexibility for both hardware and software support.<br />
<br />
==== Mercury core ====<br />
The Mercury core is a single kernel configuration that relies on the Linux kernel for the real-time capabilities.<br />
Typically this requires PREEMPT-RT support to be enabled in the kernel to meet timing requirements.<br />
The non-POSIX real-times APIs are emulated over a native threading library preferably NPTL. The Mercury configuration<br />
currently requires no Xenomai-specific kernel features but the kernel should provide CONFIG_HIGH_RES_TIMERS and<br />
PREEMPT-RT for bounded latencies.<br />
<br />
=== Licensing ===<br />
The Xenomai kernel space is licensed under GPL v2 and the user-space libraries are licensed LGPL v2.1.<br />
<br />
== EMAC Xenomai Package ==<br />
Xenomai provides several device drivers and user-space utilities in it's distribution.<br />
The device drivers rely on the Real Time Driver Model (RTDM) skin. Xenomai provides real-time drivers for <br />
CAN, serial, IPC, networking, data acquisition, and testing using the RTDM. These drivers provided can be used<br />
as a reference when creating drivers for new devices.<br />
<br />
The user-space utilities and examples are used to benchmark the target system and demonstrate the API for the RTDM drivers.<br />
<br />
The standard EMAC Xenomai package provides the basic Xenomai build for the desired target.<br />
This includes the kernel, filesystem, and SDK add-ons to start Xenomai development.<br />
<br />
=== Standard Features ===<br />
<br />
The EMAC Xenomai base package's features include:<br />
* Pre-installed Xenomai kernel and filesystem utilties<br />
* SDK add-on for Xenomai development<br />
* Basic Alchemy timer example<br />
<br />
<br />
The EMAC Xenomai package supports real-time features including:<br />
* RTDM including real-time interrupts and driver API<br />
* Timers<br />
* Real-time UART Serial (HW Dependent)<br />
* Real-time GPIO (HW Dependent)<br />
<br />
=== Additional Features ===<br />
Additional packages include:<br />
* Real-time CAN (HW Dependent)<br />
* Real-time SPI (HW Dependent)<br />
<br />
<br />
If the drivers for a particular device do not exist, EMAC provides the service of developing both real-time drivers and applications for Xenomai.<br />
For more information contact sales: http://emacinc.com/ordering-information<br />
<br />
== Further Information ==<br />
* [[Example_Xenomai_Timer|Example Xenomai Timer]]<br />
* [[Using_Xenomai_with_the_EMAC_OE_SDK|Using Xenomai with the EMAC OE SDK]]<br />
<br />
=== External Links ===<br />
* https://xenomai.org/start-here/<br />
* https://xenomai.org/introducing-xenomai-3/<br />
* https://xenomai.org//documentation/xenomai-3/html/xeno3prm/<br />
* https://en.wikipedia.org/wiki/Adaptive_Domain_Environment_for_Operating_Systems<br />
* https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Xenomai&diff=4879Xenomai2015-10-28T06:29:19Z<p>Tstratman: additional content on background, info on Xenomai 2</p>
<hr />
<div>{{todo| InProgress (10.06.2015-13:07->MW+);(10.28.2015-01:22->TS+)|Michael Welling| project=OE 5.0,MW,TS }}<br />
{{#seo:<br />
|title=Xenomai<br />
|titlemode=append<br />
|keywords=<br />
|description=About Xenomai<br />
}}<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /**************************************** Page Description Text ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
<br />
__TOC__<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** Background Information ****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:bg | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
Xenomai is a real-time operating system (RTOS) framework designed to work alongside Linux by providing several APIs for developing and running real-time applications on Linux. Xenomai can be used to add a hard real-time performance to a Linux system, operating under the limits of the hardware. The Xenomai design allows for native applications to run side-by-side with real-time applications on the same target hardware. It can also provide a migration path from a proprietary RTOS such as VxWorks, pSOS, VRTX, or uITRON to an embedded Linux environment through the use of skins providing the required APIs. <br />
<br />
Xenomai has a mature code base that is under active development tracing back to 2001, and is designed to run on many different target architectures including x86, ARM, Blackfin and NIOS2.<br />
<br />
<!-- /*********************************************************************************************************/ --><br />
<!-- /***************************************** General Information *****************************************/ --><br />
<!-- /*********************************************************************************************************/ --><br />
{{:Templateimpl:geninfo | initials=MW | title=Xenomai | desc=About Xenomai | project=OE 5.0 }}<br />
<br />
=== Xenomai 2 ===<br />
<br />
Xenomai 2 was the previous Xenomai development version at the time of this writing. It was developed for around 10 years before the development of Xenomai 3. Xenomai 2 is a dual-kernel-only system design, where the real-time Xenomai core runs alongside the Linux kernel and handles all time-critical tasks. The mechanism for this operation is provided through the ''Interrupt Pipeline'' (I-Pipe). The real-time co-kernel runs at a higher priority than all Linux tasks, only allowing Linux to run when no real-time tasks require execution and preempting Linux tasks as needed.<br />
<br />
Xenomai plans official maintenance of the Xenomai 2 branch through January of 2016.<br />
<br />
=== Xenomai 3 ===<br />
<br />
Xenomai 3 was a significant new development for the Xenomai platform. Driven by the goals of increased flexibility and improved system design and enabled by the increasing level of support and development of the native Linux PREEMPT_RT patchset, a single-kernel option was introduced (code named Mercury) while maintaining support for the traditional dual-kernel configuration (code named Cobalt).<br />
<br />
==== Cobalt core ====<br />
The Cobalt core configuration is the traditional co-kernel configuration and is the evolution of the Xenomai 2 architecture.<br />
The Linux kernel is patched to allow the Cobalt core to deal with real-time activities including interrupts and scheduling.<br />
The RTOS APIs provide an interface to the Cobalt core from user-space. The co-kernel configuration relies on the Adeos I-pipe<br />
patch for the sharing hardware resources between the kernels. EMAC uses the Cobalt configuration by default as it more closely<br />
matches our legacy Xenomai 2.x product orderings. <br />
<br />
==== Mercury core ====<br />
The Mercury core is a single kernel configuration that relies on the Linux kernel for the real-time capabilities.<br />
Typically this requires PREEMPT-RT support to be enabled in the kernel to meet timing requirements.<br />
The non-POSIX real-times APIs are emulated over a native threading library preferably NPTL. The Mercury configuration<br />
currently requires no Xenomai-specific kernel features but the kernel should provide CONFIG_HIGH_RES_TIMERS and<br />
PREEMPT-RT for bounded latencies.<br />
<br />
=== Licensing ===<br />
The Xenomai kernel space is licensed under GPL v2 and the user-space libraries are licensed LGPL v2.1.<br />
<br />
== EMAC Xenomai Package ==<br />
Xenomai provides several device drivers and user-space utilities in it's distribution.<br />
The device drivers rely on the Real Time Driver Model (RTDM) skin. Xenomai provides real-time drivers for <br />
CAN, serial, IPC, networking, data acquisition, and testing using the RTDM. These drivers provided can be used<br />
as a reference when creating drivers for new devices.<br />
<br />
The user-space utilities and examples are used to benchmark the target system and demonstrate the API for the RTDM drivers.<br />
<br />
The standard EMAC Xenomai package provides the basic Xenomai build for the desired target.<br />
This includes the kernel, filesystem, and SDK add-ons to start Xenomai development.<br />
<br />
=== Standard Features ===<br />
<br />
The EMAC Xenomai base package's features include:<br />
* Pre-installed Xenomai kernel and filesystem utilties<br />
* SDK add-on for Xenomai development<br />
* Basic Alchemy timer example<br />
<br />
<br />
The EMAC Xenomai package supports real-time features including:<br />
* RTDM including real-time interrupts and driver API<br />
* Timers<br />
* Real-time UART Serial (HW Dependent)<br />
* Real-time GPIO (HW Dependent)<br />
<br />
=== Additional Features ===<br />
Additional packages include:<br />
* Real-time CAN (HW Dependent)<br />
* Real-time SPI (HW Dependent)<br />
<br />
<br />
If the drivers for a particular device do not exist, EMAC provides the service of developing both real-time drivers and applications for Xenomai.<br />
For more information contact sales: http://emacinc.com/ordering-information<br />
<br />
== Further Information ==<br />
* [[Example_Xenomai_Timer|Example Xenomai Timer]]<br />
* [[Using_Xenomai_with_the_EMAC_OE_SDK|Using Xenomai with the EMAC OE SDK]]<br />
<br />
=== External Links ===<br />
* https://xenomai.org/start-here/<br />
* https://xenomai.org/introducing-xenomai-3/<br />
* https://xenomai.org//documentation/xenomai-3/html/xeno3prm/<br />
* https://en.wikipedia.org/wiki/Adaptive_Domain_Environment_for_Operating_Systems<br />
* https://en.wikipedia.org/wiki/Native_POSIX_Thread_Library</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3493Custom Linux Kernel Development2014-03-20T04:51:53Z<p>Tstratman: grammar correctification</p>
<hr />
<div>{{todo|Final Draft (03.18.14-13:40->MD+)|Travis Stratman|project=oe 5,TS,bs,SEOKWTODO,FinalDraft}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, you should ensure that git is installed on your development machine and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model. The needs of the community of users and developers drive feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used. This kernel tree currently covers many of EMAC OE 4's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration providing sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The <code>ls</code> utility will not show this file by default unless the <code>-a</code> option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set. One of the following values can be used:<br />
* <code>y</code> (yes)<br />
* <code>m</code> (module)<br />
* a numeric value<br />
* a string value<br />
Options not configured are entered into the file as a comment with the option followed by the phrase, "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections. The <code>grep</code> utility is often helpful when checking a kernel configuration file to determine the setting of a specific option.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command, is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select it.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]]<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task when working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the <code>Makefile</code>s and <code>Kconfig</code> are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the reader with the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized and add all devices in the carrier board spi configuration. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>. The signature of these two function pointers is:<br />
<br />
void (*func)(void)<br />
<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to ''System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Among other benefits, using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the [http://kernel.org/ kernel.org] site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and its basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: [http://www.kernel.org Kernel.org] is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Kernel Newbies<br />
: The [http://kernelnewbies.org/ Kernel Newbies] website provides information for people new to working with the Linux kernel and device drivers. The site is still a work in progress, but has some valuable information for working with the Linux kernel. It also maintains a [http://kernelnewbies.org/LinuxChanges Kernel Changelog], which is a page that gives a plain English description of the features and bugfixes which went into the kernel. The changelog also includes links to pages on other sites which provide more details on specific features and/or fixes which went into the kernel version being described. By default, the page lists the changes to the latest stable release of the kernel. The changlogs for older releases can can be viewed by appending an underscore followed by the version number (major and minor numbers only) of the kernel for which you wish to see changes to the base URL for the page (http://kernelnewbies.org/Linux). For example, to examine the changelog for the 3.12 kernel, take the base URL, http://kernelnewbies.org/Linux, and append _3.12 to form [http://kernelnewbies.org/Linux_3.12 http://kernelnewbies.org/Linux_3.12].<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3492Custom Linux Kernel Development2014-03-20T04:49:20Z<p>Tstratman: /* Testing */ fixed italics</p>
<hr />
<div>{{todo|Final Draft (03.18.14-13:40->MD+)|Travis Stratman|project=oe 5,TS,bs,SEOKWTODO,FinalDraft}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, you should ensure that git is installed on your development machine and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model. The needs of the community of users and developers drive feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used. This kernel tree currently covers many of EMAC OE 4's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration providing sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The <code>ls</code> utility will not show this file by default unless the <code>-a</code> option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set. One of the following values can be used:<br />
* <code>y</code> (yes)<br />
* <code>m</code> (module)<br />
* a numeric value<br />
* a string value<br />
Options not configured are entered into the file as a comment with the option followed by the phrase, "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections. The <code>grep</code> utility is often helpful when checking a kernel configuration file to determine the setting of a specific option.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command, is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select it.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]]<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task when working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the <code>Makefile</code>s and <code>Kconfig</code> are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the reader with the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized and adds all devices in the carrier board spi configuration. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>. The signature of these two function pointers is:<br />
<br />
void (*func)(void)<br />
<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to ''System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Among other benefits, using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the [http://kernel.org/ kernel.org] site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and its basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: [http://www.kernel.org Kernel.org] is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Kernel Newbies<br />
: The [http://kernelnewbies.org/ Kernel Newbies] website provides information for people new to working with the Linux kernel and device drivers. The site is still a work in progress, but has some valuable information for working with the Linux kernel. It also maintains a [http://kernelnewbies.org/LinuxChanges Kernel Changelog], which is a page that gives a plain English description of the features and bugfixes which went into the kernel. The changelog also includes links to pages on other sites which provide more details on specific features and/or fixes which went into the kernel version being described. By default, the page lists the changes to the latest stable release of the kernel. The changlogs for older releases can can be viewed by appending an underscore followed by the version number (major and minor numbers only) of the kernel for which you wish to see changes to the base URL for the page (http://kernelnewbies.org/Linux). For example, to examine the changelog for the 3.12 kernel, take the base URL, http://kernelnewbies.org/Linux, and append _3.12 to form [http://kernelnewbies.org/Linux_3.12 http://kernelnewbies.org/Linux_3.12].<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3491Custom Linux Kernel Development2014-03-20T04:47:37Z<p>Tstratman: /* Where to go for Additional Information */ added link, fixed spacing</p>
<hr />
<div>{{todo|Final Draft (03.18.14-13:40->MD+)|Travis Stratman|project=oe 5,TS,bs,SEOKWTODO,FinalDraft}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, you should ensure that git is installed on your development machine and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model. The needs of the community of users and developers drive feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used. This kernel tree currently covers many of EMAC OE 4's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration providing sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The <code>ls</code> utility will not show this file by default unless the <code>-a</code> option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set. One of the following values can be used:<br />
* <code>y</code> (yes)<br />
* <code>m</code> (module)<br />
* a numeric value<br />
* a string value<br />
Options not configured are entered into the file as a comment with the option followed by the phrase, "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections. The <code>grep</code> utility is often helpful when checking a kernel configuration file to determine the setting of a specific option.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command, is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select it.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]]<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task when working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the <code>Makefile</code>s and <code>Kconfig</code> are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the reader with the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized and adds all devices in the carrier board spi configuration. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>. The signature of these two function pointers is:<br />
<br />
void (*func)(void)<br />
<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Among other benefits, using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the [http://kernel.org/ kernel.org] site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and its basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: [http://www.kernel.org Kernel.org] is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Kernel Newbies<br />
: The [http://kernelnewbies.org/ Kernel Newbies] website provides information for people new to working with the Linux kernel and device drivers. The site is still a work in progress, but has some valuable information for working with the Linux kernel. It also maintains a [http://kernelnewbies.org/LinuxChanges Kernel Changelog], which is a page that gives a plain English description of the features and bugfixes which went into the kernel. The changelog also includes links to pages on other sites which provide more details on specific features and/or fixes which went into the kernel version being described. By default, the page lists the changes to the latest stable release of the kernel. The changlogs for older releases can can be viewed by appending an underscore followed by the version number (major and minor numbers only) of the kernel for which you wish to see changes to the base URL for the page (http://kernelnewbies.org/Linux). For example, to examine the changelog for the 3.12 kernel, take the base URL, http://kernelnewbies.org/Linux, and append _3.12 to form [http://kernelnewbies.org/Linux_3.12 http://kernelnewbies.org/Linux_3.12].<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3490Custom Linux Kernel Development2014-03-20T04:43:01Z<p>Tstratman: minor edits</p>
<hr />
<div>{{todo|Final Draft (03.18.14-13:40->MD+)|Travis Stratman|project=oe 5,TS,bs,SEOKWTODO,FinalDraft}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, you should ensure that git is installed on your development machine and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model. The needs of the community of users and developers drive feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used. This kernel tree currently covers many of EMAC OE 4's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration providing sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The <code>ls</code> utility will not show this file by default unless the <code>-a</code> option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set. One of the following values can be used:<br />
* <code>y</code> (yes)<br />
* <code>m</code> (module)<br />
* a numeric value<br />
* a string value<br />
Options not configured are entered into the file as a comment with the option followed by the phrase, "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections. The <code>grep</code> utility is often helpful when checking a kernel configuration file to determine the setting of a specific option.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command, is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select it.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]]<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task when working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the <code>Makefile</code>s and <code>Kconfig</code> are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the reader with the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized and adds all devices in the carrier board spi configuration. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>. The signature of these two function pointers is:<br />
<br />
void (*func)(void)<br />
<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Among other benefits, using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the [http://kernel.org/ kernel.org] site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and its basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Kernel Newbies<br />
: The [http://kernelnewbies.org/ Kernel Newbies] website provides information for people new to working with the Linux kernel and device drivers. The site is still a work in progress, but has some valuable information for working with the Linux kernel. It also maintains a [http://kernelnewbies.org/LinuxChanges Kernel Changelog], which is a page that gives a plain English description of the features and bugfixes which went into the kernel. The changelog also includes links to pages on other sites which provide more details on specific features and/or fixes which went into the kernel version being described. By default, the page lists the changes to the latest stable release of the kernel. The changlogs for older releases can can be viewed by appending an underscore followed by the version number (major and minor numbers only) of the kernel for which you wish to see changes to the base URL for the page (http://kernelnewbies.org/Linux). For example, to examine the changelog for the 3.12 kernel, take the base URL, http://kernelnewbies.org/Linux, and append _3.12 to form [http://kernelnewbies.org/Linux_3.12 http://kernelnewbies.org/Linux_3.12]. <br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3316Custom Linux Kernel Development2014-02-25T12:42:36Z<p>Tstratman: marked for review again</p>
<hr />
<div>{{todo|Review|Travis Stratman|project=oe 5,TS,Review}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and developers driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]] '''*** NOTE you probably should be more clear about how to do this on this or one of the other LILO pages '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3315Custom Linux Kernel Development2014-02-25T12:41:42Z<p>Tstratman: marked for review</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,Review}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and developers driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]] '''*** NOTE you probably should be more clear about how to do this on this or one of the other LILO pages '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3311Custom Linux Kernel Development2014-02-22T23:43:00Z<p>Tstratman: /* Building and Deployment */ added links</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and developers driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader:<br />
* U-Boot: [[Loading Images with U-Boot]]<br />
* RedBoot: [[Loading Images with RedBoot]]<br />
* LILO: [[Installing LILO]] '''*** NOTE you probably should be more clear about how to do this on this or one of the other LILO pages '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3310Custom Linux Kernel Development2014-02-22T23:35:12Z<p>Tstratman: added links</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and developers driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' ********* More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config FTS_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_FTS_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the FTS carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the FTS system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in [https://www.kernel.org/doc/Documentation/CodingStyle <code>Documentation/CodingStyle</code>] to keep formatting and standards consistent and ease adoption.<br />
# During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. [https://www.kernel.org/doc/Documentation/SubmittingDrivers <code>Documentation/SubmittingDrivers</code>] has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3309Custom Linux Kernel Development2014-02-22T23:29:43Z<p>Tstratman: cleanup</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems as well as additional kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. <br />
<br />
Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and developers driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has a feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several top-level directories. Table 1 gives a brief description of each of these directories which will be referred to throughout this document.<br />
<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
Once created, the current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the <code>make</code> system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code> holds default configuration files for ARM targets.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly exposing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' ********* More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and make adjustments as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. You will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, and micro-SD (MMC), as well as references to the <code>cspec</code> ("carrier specification") structure. The carrier specification structure is defined by code in the carrier board file. It determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This code generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the end of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> structure. This function is shown below for reference:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is ''FTS''. To implement support for this hardware, start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-fts.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-fts.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "FTS Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-fts.c</code> file that was created when the <code>CONFIG_FTS_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-fts.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-fts.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the FTS carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the FTS board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the FTS hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the FTS board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''FTS Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in <code>Documentation/CodingStyle</code> to keep formatting consistent and ease adoption.<br />
<br />
During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for inclusion into the mainline kernel. <code>Documentation/SubmittingDrivers</code> has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3308Custom Linux Kernel Development2014-02-22T14:47:26Z<p>Tstratman: background info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is the heart of the GNU/Linux OS and is developed by a community of thousands of contributors across the globe. Linux follows an evolutionary development model, with the needs of the community of users and companies driving feature development, while Linus Torvalds -- the "father" of Linux -- integrates and releases these features and improvements into the mainline ("vanilla") kernel branch.<br />
<br />
Linux is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. However, kernel drivers and features may be compiled as modules which may be loaded or unloaded dynamically on a running system. The kernel includes support for many different architectures, and has an impressive feature set including preemption, virtual memory, shared libraries, virtualization, and complete networking stacks.<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
This directory structure will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in <code>Documentation/CodingStyle</code> to keep formatting consistent and ease adoption.<br />
<br />
During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for consideration of inclusion into the Kernel. <code>Documentation/SubmittingDrivers</code> has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3302Custom Linux Kernel Development2014-02-17T13:01:03Z<p>Tstratman: driver and background info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
<br />
The Linux kernel is a monolithic kernel, meaning that the kernel is responsible for defining a complete interface to the system hardware. Also, kernel drivers and features may be compiled as modules and loaded or unloaded dynamically on a running system. <br />
<br />
<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
*** DESCRIBE ME http://www.makelinux.net/kernel_map/<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Overview ===<br />
Device drivers provide a direct interface to a hardware device through a well-defined programming interface. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know the underlying hardware interface because the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. <br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below (see Linux Device Drivers Edition 3, Chapter 1 for more detailed information):<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points should be considered as part of the driver development:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in <code>Documentation/CodingStyle</code> to keep formatting consistent and ease adoption.<br />
<br />
During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for consideration of inclusion into the Kernel. <code>Documentation/SubmittingDrivers</code> has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3287Custom Linux Kernel Development2014-02-12T13:06:00Z<p>Tstratman: more driver info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below <ref>Linux Device Drivers Edition 3, Chapter 1</ref>:<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system also implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be implemented. Several points may be considered for this:<br />
# Where appropriate, use existing drivers from the stable kernel as a model for implementing new code.<br />
# Add Kconfig and Makefile entries as needed to support configuration of the driver.<br />
# While programming, follow the Linux kernel coding style as described in <code>Documentation/CodingStyle</code> to keep formatting consistent and ease adoption.<br />
<br />
During and following code development, the driver should be fully tested on the hardware.<br />
<br />
==== Share ====<br />
Once you have developed a kernel driver, you may want to consider becoming involved in the Linux community and submitting the driver as a patch for consideration of inclusion into the Kernel. <code>Documentation/SubmittingDrivers</code> has more information on this process and requirements.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3286Custom Linux Kernel Development2014-02-12T12:51:37Z<p>Tstratman: intermediate driver info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below <ref>Linux Device Drivers Edition 3, Chapter 1</ref>:<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system also implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first steps in developing or expanding a driver for a particular device include obtaining information about the device and determining what drivers already exist for this device or similar devices. This process may start through Internet searches, requesting information from the manufacturer, and searching through the kernel source as well as the source for the most recent kernels on the Kernel.org site. Review of any existing drivers should provide a good idea of where your driver should fall in the kernel, what APIs it should use, and it's basic structure. Depending on the device there may be several valid options which will need to be evaluated based on the needs of the application.<br />
<br />
Once the location and structure of the driver have been decided, the code may be started. <br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3285Custom Linux Kernel Development2014-02-10T13:46:07Z<p>Tstratman: driver structure</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below <ref>Linux Device Drivers Edition 3, Chapter 1</ref>:<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system also implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits.<br />
<br />
A simple example of the driver model is the SPI subsystem, which provides a core SPI API with support for SPI controller drivers and SPI protocol drivers. Controller drivers provide direct access to the hardware, transmitting and receiving data on the physical pins. Protocol drivers pass messages through the controller driver to communicate with other devices using a specific protocol. Kernel and userlevel APIs are provided for initializing, declaring, and accessing SPI devices. Creating a new SPI controller driver is a matter of providing code to support the functions required by the SPI controller core that behave as specified and registering the driver during initialization. See <code>Documentation/spi/</code>, <code>drivers/spi/</code>, and <code>include/linux/spi/</code> to examine this structure.<br />
<br />
=== Driver Development Process ===<br />
<br />
The first step in developing a driver is determining ...<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3284Custom Linux Kernel Development2014-02-08T15:47:37Z<p>Tstratman: driver development info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major classes of device drivers apply in some way to most drivers in the Linux kernel as described below <ref>Linux Device Drivers Edition 3, Chapter 1</ref>:<br />
; Character device drivers<br />
: Character devices, also known as ''char'' devices, are able to be accessed similar to a file, where a stream of data can be used as an abstraction to represent the device. Serial ports are one example of character devices. <br />
; Block device drivers<br />
: Block devices require data transfer in a specific block size, such as storage devices. Although the kernel interface to a block device is specialized, the interface to the user works exactly like a character device in that it accepts reading and writing a stream of any number of bytes.<br />
; Network interface drivers<br />
: Network interfaces are capable of communication across a network and are generally hardware devices, such as the "MACB" controller on Atmel hardware or a NIC on a PC. A network interface driver handles packet transmission, and identifies each device with a unique name on the system, such as <code>eth0</code>.<br />
<br />
The Linux kernel device driver system also implements a layered approach at development. This means that specific devices are separated into subsystems, which implement a common API and share core code between all drivers. Using this approach speeds development time and maintenance, ensures a common interface, and encourages code reuse among other benefits. An example is the SPI layer, which **************<br />
<br />
=== Driver Development Process ===<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3283Custom Linux Kernel Development2014-02-07T13:17:06Z<p>Tstratman: minor edit</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Linux Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. There are many types of drivers in the Linux kernel, and many drivers can be classified in several different ways. Three major <br />
<br />
=== Driver Development Process ===<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3270Custom Linux Kernel Development2014-02-05T13:01:07Z<p>Tstratman: initial driver development content</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment|Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Device drivers provide a direct interface to a hardware device through a well-defined standard programming API. This makes the device accessible to userspace and other kernel code without requiring any knowledge of what is happening at the hardware level. For example, a CAN bus controller may be memory mapped to the processor, while another connects through the SPI bus. The user does not need to know which method is used, the CAN API is used to abstract this and the same application code may be used with either device. Furthermore, the driver for the SPI-based CAN chip may be used on different systems without porting as it uses the standard SPI API to interface with the SPI controller through the SPI driver written for the processor it is being used on. Developing and examining device driver code is often required through the course of embedded systems development, particularly due to the specialized devices used. This section provides a quick overview of device driver development on the Linux Kernel.<br />
<br />
=== Driver Structure ===<br />
<br />
As an open source operating system, all of the source code for device drivers on the system (except for any proprietary binary modules as discussed in [[#Licensing|Licensing]] below) are available for reference and analysis. <br />
<br />
=== Driver Development Process ===<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Using_the_EMAC_GPIO_Class&diff=3264Using the EMAC GPIO Class2014-01-31T12:37:03Z<p>Tstratman: updated project tags</p>
<hr />
<div>{{todo|Complete; List related hardware eventually; (12.17.13-18:20->KY+);(12.18.13-19:00->MD+);(12.19.13-11:21->MW+);(01.14.14-14:20->KY-);(01.15.14-14:00->KY+);(01.16.14-14:00->MD+);(01.25.14-14:19->TS+)|Klint Youngmeyer|project=oe 4, oe 5,mw,ky,Complete,md,ts}}<br />
<br />
The EMAC GPIO Class is a generic programming interface for General Purpose Input Output (GPIO) devices in the Linux Kernel. The GPIO class driver has two main interfaces under standard Linux: Linux sysfs and character device. The GPIO class is extremely flexible and uses a set of function pointers at the kernel level to allow for specialized read/write functions for each device. EMAC utilizes the GPIO class to create devices that use the same simple interface, such as GPIO registers, simple configuration variables, hardware registers, and Analog-to-Digital converter drivers where the user needs to retrieve a single value from the device.<br />
<br />
==Supported Devices==<br />
Most of EMAC's ARM based SOM-Carrier combinations and some of EMAC's x86 boards support the EMAC GPIO Class. For a list of GPIOs on each device, please see the EMAC website at [http://emacinc.com/products/system_on_module emacinc.com/products/system_on_module].<br />
<br />
==Components==<br />
<br />
An EMAC GPIO Class Device has three main components. A clear understanding of these components is important for proper use and implementation.<br />
<br />
===Data===<br />
<br />
The <code>data</code> member of a GPIO device is the primary component. In the most simple devices, this is the only component accessible from userspace. The <code>data</code> member is read and/or written to access or set the current value of the GPIO device. The actual function of the <code>data</code> member is implementation specific. For a GPIO device in its purest form, such as the GPIO ports present in many of EMAC's CPLD designs, the <code>data</code> member is a register value with each of the 8 least significant bits representing the digital state of a single line in the GPIO port. In contrast, A/D devices implemented with the EMAC GPIO Class will typically provide the analog value of the currently selected channel in the <code>data</code> member.<br />
<br />
The <code>data</code> member is allocated as a 32-bit unsigned integer regardless of implementation. Many devices use only the least significant byte or the least significant bit. <br />
<!--Data Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int data;<br />
int output = 42;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will write the contents of the variable 'output' to /dev/portc<br />
if (ioctl(fd_out, DATAWRITE, &output)<0){<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will read the digital value of /dev/portb to the the variable 'data' <br />
if (ioctl(fd_out, DATAREAD, &data)<0)<br />
{<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===DDR===<br />
<br />
The <code>ddr</code> or Data Direction Register is a member of the EMAC GPIO Class that is used primarily for direction-configurable GPIO devices. Many devices do not register this aspect of the interface. The <code>ddr</code> member is used to determine if a particular device should act as an input or output. Depending on the implementation, many devices are bit-configurable GPIO devices, meaning that each bit/line in the GPIO device can be configured as an input or output by its respective value in the <code>ddr</code>. Typically, a '1' value in the <code>ddr</code> configures the device as an output and a '0' value in the ddr configures the device as an input. Bidirectional GPIO devices are generally configured as inputs by default until explicitly configured as an output to prevent hardware contention.<br />
<br />
For example, an EMAC GPIO Class device porta is a one-byte bit-configurable bidirectional GPIO device. Each bit in the <code>data</code> register corresponds to the digital status of the corresponding line porta[0-7]. On reset, the <code>ddr</code> member is read at <code>0x00</code>, indicating that the device is configured with all lines as inputs. If the <code>ddr</code> member is set to <code>0xAA</code> (binary 1010 1010) bits 0, 2, 4, and 6 will remain configured as inputs while the rest of the bits will be configured as outputs. Reading and setting the value in the <code>data</code> member will react according to the configuration set in the <code>ddr</code>. The <code>ddr</code> is allocated as a 32-bit unsigned integer regardless of implementation.<br />
<!--DDR Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int input = 0x00;<br />
int output = 0xff;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will set the data direction of /dev/portc to all outputs as denoted by output=0xff<br />
if (ioctl(fd_out, DDRWRITE, &output)<0)<br />
{<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_in = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will set the data direction of /dev/portb to all inputs as denoted by input=0x00<br />
if (ioctl(fd_out, DDRWRITE, &input)<0)<br />
{<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===Index===<br />
<br />
Many EMAC GPIO Class devices are implemented as indexed GPIO Devices. These devices utilize a member named <code>index</code> which impacts the device according to the implementation. The <code>index</code> member is typically used to specify a memory offset from some base for the <code>data</code> member or some type of channel setting or controller selection. Many devices ignore the <code>index</code> value or do not register this member at all.<br />
<br />
An example of an indexed GPIO Class device is the <code>indexed_atod</code> device (and other A/D devices) found on many EMAC boards. In this case, the <code>index</code> member is used to set the current channel of the A/D to read from the <code>data</code> member. When the <code>index</code> is set to 0, channel 0 will be accessed. When the index is set to 3, the <code>data</code> register will reflect the current value on channel 3 of the device. Another example would be two identical counter registers in a device where setting the index would control which counter was accessed when reading the <code>data</code> register. This would be an alternative to registering a separate device for each counter.<br />
<br />
Indexed GPIO devices should check the applicable range for the <code>index</code> when the user attempts to set the device. For example, an 8-channel A/D device implemented as an EMAC GPIO Class device would have a valid range for the <code>index</code> member of 0-7. Attempting to set the <code>index</code> to anything greater than 7 would cause the <code>index</code> to be set to the maximum allowed value of 7.<br />
<!--Index Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int index_c = 1;<br />
int index_b;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will set the AtoD index for /dev/portc<br />
if (ioctl(fd_out, INDEXWRITE, &index_c)<0)<br />
{<br />
fprintf(stderr,"error setting index: %s\n", strerror(errno));<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will read the AtoD index for /dev/portb into index_b<br />
if (ioctl(fd_out, INDEXREAD, &index_b)<0)<br />
{<br />
fprintf(stderr,"error reading index: %s\n", strerror(errno));<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===Lock===<br />
<br />
{{imbox | type = notice | text = '''Note:''' Locking support is currently not available on all EMAC boards. This feature was introduced in the later versions of the 2.6.28 kernel for the AT91-based boards. It will be implemented in other kernel trees in the future.}}<br />
<br />
<br />
Many GPIO devices may be accessed by multiple processes simultaneously, which leads to the possibility of race conditions. The EMAC GPIO Class includes a locking mechanism to prevent these cases when used correctly. Without the locking mechanism, synchronization needs to be performed in userspace.<br />
<br />
The lock is implemented as a <code>struct mutex</code> in the GPIO Class device structure. The lock is obtained by the GPIO driver interface through a call to <code>mutex_lock()</code> and freed using <code>mutex_unlock()</code>. This means that any attempts to lock an already locked device will cause the caller to sleep until the lock is freed by the process holding the lock. A nonblocking method using <code>mutex_trylock()</code> may be implemented in the future.<br />
<br />
All access to a device must be synchronized using the lock. Further details on this implementation are described in later sections.<br />
<br />
==User Interfaces==<br />
<br />
This section describes the two user interfaces available for the GPIO class. The sysfs layer is very handy for scripting and testing. For higher performance and more flexible access, the character driver interface is used, generally from a C application. This provides a simple <code>ioctl()</code> interface.<br />
<br />
=== Sysfs ===<br />
The <code>sysfs</code> filesystem is a virtual filesystem provided by the Linux kernel that allows for a file-based interface to kernel driver parameters. The EMAC GPIO Class utilizes <code>sysfs</code> to provide a simple read/write interface to the GPIO Class device. This interface is easily accessible from the Linux shell and through shell scripting.<br />
<br />
The GPIO Class driver registers a directory at <code>/sys/class/gpio</code> assuming that sysfs has been mounted on the system. Under this directory, every GPIO Class device registered with the system will have a directory (i.e. <code>/sys/class/gpio/porta</code>). Within this directory, there will be some files that are a part of the sysfs heirarchy as well as the GPIO Class interface files <code>data</code>, <code>ddr</code>, and <code>index</code>. Depending on the type of device and its implementation, the <code>ddr</code> and <code>index</code> files may or may not exist; <code>data</code> should always be present.<br />
<br />
<br />
{{imbox | text = '''Note:''' The <code>/sys/class/gpio</code> directory is used by the new I/O driver code in the standard Linux kernel tree. This location will be changed by EMAC in the near future to avoid conflict.}}<br />
<br />
==== Reading ====<br />
<br />
Reading the current value of a device's settings is as simple as reading the respective file. The <code>cat</code> command is typically used for this. The output is formatted as ASCII hexadecimal characters. For example, to read the value of the data member of the <code>porta</code> device, run the command: <br />
<br />
<syntaxhighlight lang=console><br />
emac-oe$ cat /sys/class/gpio/porta/data<br />
</syntaxhighlight><br />
<br />
The implementation of the read function for the <code>data</code>, <code>ddr</code>, and <code>index</code> members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The actual value returned depends on the device implementation.<br />
<br />
==== Writing ====<br />
<br />
Writing a new setting to a member of the GPIO device through the sysfs interface is accomplished by writing a new value to the respective file. The <code>echo</code> command is typically used along with file redirection to set the new value directly, although the output of any command could be used as long as it is formatted correctly. For example, to set the <code>porta</code> device to <code>0xFF</code> (all on) the user would first set all bits to output using the <code>ddr</code> register and then write <code>0xFF</code> to the data register as shown below: <br />
<br />
<syntaxhighlight lang=console><br />
emac-oe$ echo 0xff > /sys/class/gpio/porta/ddr<br />
emac-oe$ echo 0xff > /sys/class/gpio/porta/data<br />
</syntaxhighlight><br />
<br />
The implementation of the write function for the <code>data</code>, <code>ddr</code>, and <code>index</code> members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The low-level effects of the write function depends on the device implementation.<br />
<br />
=== Character Driver ===<br />
<br />
The character driver interface is the preferred method for accessing EMAC GPIO Class devices from programmed applications. This interface is significantly more efficient than the sysfs layer and easier to program. In kernels that support the GPIO Class locking mechanism, the character driver interface offers user control over the lock that is not available using the sysfs interface. The character driver interface uses the <code>ioctl()</code> system call. Newer kernels also support an <code>fasync</code> method for signal-based event notification from the driver to the user application.<br />
<br />
==== Available IOCTLs ====<br />
<br />
Several different <code>ioctl</code> commands are available for use. The user must know the supported features of the device before using an <code>ioctl</code> command. For example, many devices do not support the <code>ddr</code> or <code>index</code> functionality. All <code>ioctl</code> commands will return a negative error code on failure.<br />
<br />
===== Locking =====<br />
The ioctl commands in this section will acquire and free the GPIO lock on kernels that include support for the lock. These commands are the most efficient to use when a single GPIO read/write is required. On kernels that do not support the GPIO lock, these commands simply perform the advertised action. For commands which read a value, the ioctl will store the value read into a 32-bit integer which is passed to it via a pointer. For commands which write a value, the ioctl takes a pointer to the 32-bit integer which holds the value to be written.<br />
<br />
* <code>DATAREAD</code>: Read the current value of the device's <code>data</code> member by calling the <code>data_read</code> function.<br />
* <code>DATAWRITE</code>: Write a new value to the device's <code>data</code> member by calling the <code>data_write</code> function.<br />
* <code>DDRREAD</code>: Read the current value of the device's <code>ddr</code> member by calling the <code>ddr_read</code> function.<br />
* <code>DDRWRITE</code>: Write a new value to the device's <code>ddr</code> member by calling the <code>ddr_write</code> function.<br />
* <code>INDEXREAD</code>: Read the current value of the device's <code>index</code> member by calling the <code>index_read</code> function.<br />
* <code>INDEXWRITE</code>: Write a new value to the device's <code>index</code> member by calling the <code>index_write</code> function.<br />
<br />
===== Lock Control =====<br />
The ioctl commands in this section are only available on kernels that support the GPIO Class locking mechanism. They are used to control the current state of the lock.<br />
<br />
* <code>GPIOLOCK</code>: Lock the device's mutex through a call to <code>mutex_lock()</code>. This command will sleep until the lock has been acquired.<br />
* <code>GPIOUNLOCK</code>: Release the device's mutex through a call to <code>mutex_unlock()</code>. This command should not be called unless the lock has already been acquired using <code>GPIOLOCK</code>.<br />
<br />
===== No-Lock =====<br />
The ioctl commands in this section do not affect the lock of the GPIO device and are only available in kernels which support the GPIO Class locking feature. These are lock-free versions of the standard commands listed in the [[#Locking|Locking]] section. Before calling one of these commands, the process must acquire the lock using the <code>GPIOLOCK</code> command. These commands allow synchronization between multiple processes or threads when accessing the same device. For example, when performing a read followed by a write, the lock would need to be held for the duration of both commands to ensure that incorrect values are not written to the device. These commands can also be used to provide higher performance when writing and/or reading several values in a batch; the lock should be acquired before the batch and released afterwards.<br />
<br />
* <code>DATAREAD_NL</code>: Read the current value of the device's <code>data</code> member.<br />
* <code>DATAWRITE_NL</code>: Write a new value to the device's <code>data</code> member.<br />
* <code>DDRREAD_NL</code>: Read the current value of the device's <code>ddr</code> member.<br />
* <code>DDRWRITE_NL</code>: Write a new value to the device's <code>ddr</code> member.<br />
* <code>INDEXREAD_NL</code> the current value of the device's <code>index</code> member.<br />
* <code>INDEXWRITE_NL</code>: Write a new value to the device's <code>index</code> member.<br />
<br />
===== Asynchronous Notification =====<br />
The ioctl commands in this section are for use with the asynchronous notification feature of the EMAC GPIO Class. Most devices do not use this feature, and these commands are only available on kernels that support this feature. The low-level implementation is device-specific.<br />
<br />
* <code>SETNOTIFY</code>: Set a new notification bitmask for the current file descriptor. The value is passed to the ioctl call as a pointer to a 32-bit integer. The gpio lock is acquired and released during this command.<br />
<br />
For the following commands, the value is returned via a pointer to a 32-bit integer passed to the ioctl call. The gpio lock is not acquired and does not need to be held for these commands.<br />
* <code>GETNOTIFY</code>: Get the current notification bitmask for this file descriptor.<br />
* <code>DATAREADQ</code>: Read the first value from the data queue.<br />
* <code>GETQUEUESIZE</code>: Read the current number of values in the data queue for this file descriptor.<br />
<br />
==== Programming ====<br />
<br />
The following general examples demonstrate the character driver programming interface. <br />
<br />
<br />
{{imbox | type=content| text=The examples below do not check the return value of calls for errors. Be sure to check for and handle errors in a production system.}}<br />
<br />
<br />
To access a device from a C application, it must first be opened using ''open()'': <br />
<syntaxhighlight lang=c><br />
int fd;<br />
fd = open(DEVICE, O_RDWR);<br />
...<br />
close(fd);<br />
</syntaxhighlight><br />
<br />
If the open command is successful, any supported ioctl command may be used to access the device. The example below sets the value of the ''data'' member to 0xFF<br />
<br />
<syntaxhighlight lang=c><br />
__u32 arg;<br />
...<br />
arg = 0xff;<br />
ioctl(fd, DATAWRITE, &arg);<br />
</syntaxhighlight><br />
<br />
The example below uses the locking mechanism to perform a sequence of accesses to a device:<br />
<syntaxhighlight lang=c><br />
#define CONTROLBIT (1 << 3)<br />
__u32 arg;<br />
...<br />
ioctl(fd, GPIOLOCK, NULL);<br />
arg = 1;<br />
ioctl(fd, INDEXWRITE_NL, &arg);<br />
ioctl(fd, DATAREAD_NL, &arg);<br />
/* set control bit */<br />
arg &= CONTROLBIT;<br />
ioctl(fd, DATAWRITE_NL, &arg);<br />
ioctl(fd, GPIOUNLOCK, NULL);<br />
</syntaxhighlight><br />
<br />
==== Asynchronous Notification Example ====<br />
<br />
Asynchronous notification for the EMAC GPIO Class is a new feature available in some kernels. This was added to the driver at the same time as locking support and utilizes the <code>fasync</code> system call. Essentially, this feature allows the kernel driver to notify the user application of some event through a signal. Typically this is used for devices which support hardware interrupts. Currently, no standard EMAC devices utilize the asynchronous notification feature.<br />
<br />
For each open file descriptor of a certain device, it is possible to set a notification mask indicating which types of events will trigger notification as well as which signal will be sent to the process from the driver. The default signal is <code>SIGIO</code>. When an event occurs, a value will be written to a queue for each file descriptor that is registered for notification of the event. The notification mask, events, and queue functionality are all implementation-specific.<br />
<br />
The following example utilizes the asynchronous notification interface for a device that supports it. This particular device is an interrupt-enabled register that will notify a process if the type of interrupt that occurs matches the notification mask of the particular file descriptor. When an applicable interrupt occurs, the data register will immediately be queued into the file descriptor specific data queue.<br />
<br />
<br />
{{imbox | text='''Note:''' The device utilized in the example below is an example device which does not exist on any EMAC system. The example is provided to illustrate the asynchronous notification interface which may be available on a system for a real device.}}<br />
<br />
<br />
=====gpio-fasync-example.c=====<br />
<syntaxhighlight lang=c><br />
#define _GNU_SOURCE<br />
<br />
#include <fcntl.h><br />
#include <sys/types.h><br />
#include <sys/stat.h><br />
#include <sys/ioctl.h><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <asm/types.h><br />
#include <signal.h><br />
#include "gpio_char.h"<br />
<br />
static sig_atomic_t caught = 0;<br />
static sig_atomic_t run = 1;<br />
<br />
void sig_handle(int sig)<br />
{<br />
if (sig == SIGIO)<br />
caught = 1;<br />
else /* termination */<br />
run = 0;<br />
}<br />
<br />
#define DEVICE "/dev/gpio_async"<br />
#define NOTIFY_MASK (1 << 4)<br />
<br />
/**<br />
* function to enable asynchronous notification on the given file descriptor<br />
* for the specified signal<br />
* @param fd the open GPIO device file descriptor to enable notification for<br />
* @param sig the signal to be sent by the kernel for event notification<br />
*/<br />
static void set_fasync(int fd, int sig);<br />
<br />
/**<br />
* function to set the event notification flags for the driver on a given <br />
* file descriptor.<br />
* @param fd the open GPIO device file descriptor for notification<br />
* @param notify bitmask specifying which events this file descriptor should<br />
* be notified on<br />
* @return the result of the ioctl() call to set the notification flags<br />
*/<br />
static int set_notify_flags(int fd, __u32 notify);<br />
<br />
/**<br />
* function to get the queue size for the given file descriptor<br />
* @param fd the open GPIO device file descriptor to query<br />
* @return the current queue size as reported by the driver<br />
*/<br />
static __u32 get_queue_size(int fd);<br />
<br />
int main(int argc, char *argv[]){<br />
<br />
int fd;<br />
__u32 data;<br />
struct sigaction sact;<br />
sigset_t block_mask;<br />
sigset_t suspend_mask;<br />
sigset_t old_mask;<br />
<br />
/* set up signal handlers */<br />
sact.sa_handler = sig_handle;<br />
sigemptyset(&sact.sa_mask);<br />
sact.sa_flags = 0;<br />
sigaction(SIGIO, &sact, NULL);<br />
sigaction(SIGTERM, &sact, NULL);<br />
sigaction(SIGINT, &sact, NULL);<br />
<br />
/* Open all devices */<br />
if ((fd = open(DEVICE, O_RDWR)) <= 0) {<br />
fprintf(stderr, "Error on open %s\n", DEVICE);<br />
exit(EXIT_FAILURE);<br />
}<br />
<br />
/* allow sigsuspend to be interrupted by any signal */<br />
sigemptyset(&suspend_mask);<br />
<br />
/* <br />
* note that it is advantageous to mask all requested signals at<br />
* this point until all configuration is completed at which point<br />
* they will be unmasked by sigsuspend(). This also makes sense for<br />
* the implementation here, as the signals will be blocked again after<br />
* sigsuspend() returns during the DATAREADQ calls, preventing race<br />
* conditions. The call to sigprocmask() below does this.<br />
*/<br />
sigemptyset(&block_mask);<br />
sigaddset(&block_mask, SIGIO);<br />
<br />
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);<br />
<br />
/* enable fasync notification on device */<br />
set_fasync(fd, SIGIO);<br />
<br />
/* Inform the driver which flags each fd should be notified on */<br />
set_notify_flags(fd, NOTIFY_MASK);<br />
<br />
printf("Waiting for signals\n");<br />
fflush(stdout);<br />
<br />
while (run) {<br />
sigsuspend(&suspend_mask);<br />
if (caught) {<br />
while (get_queue_size(fd) > 0) {<br />
ioctl(fd, DATAREADQ, &data);<br />
printf("Queued value 0x%X\n", data);<br />
caught = 0;<br />
}<br />
}<br />
}<br />
<br />
printf("Terminating...\n");<br />
close(fd);<br />
<br />
exit(EXIT_SUCCESS);<br />
}<br />
<br />
static void set_fasync(int fd, int sig)<br />
{<br />
int flags;<br />
<br />
flags = fcntl(fd, F_GETFL);<br />
flags |= FASYNC;<br />
/* set owner... tells who to send the signal to */<br />
/* <br />
* note that in a threaded application, getpid() should be replaced<br />
* with getid()<br />
*/<br />
fcntl(fd, F_SETOWN, getpid());<br />
fcntl(fd, F_SETSIG, sig);<br />
/* Now that configuration is complete, set FASYNC mode */<br />
fcntl(fd, F_SETFL, flags);<br />
}<br />
<br />
static int set_notify_flags(int fd, __u32 notify)<br />
{<br />
return ioctl(fd, SETNOTIFY, &notify);<br />
}<br />
<br />
static __u32 get_queue_size(int fd)<br />
{<br />
__u32 data;<br />
<br />
ioctl(fd, GETQUEUESIZE, &data);<br />
return data;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
=====gpio_char.h=====<br />
<syntaxhighlight lang=c><br />
#ifndef GPIO_CHAR_H_<br />
#define GPIO_CHAR_H_<br />
<br />
/* Userspace version of kernel header file */<br />
<br />
#include <linux/ioctl.h><br />
<br />
#define RTDM_CLASS_GPIO 0x80 <br />
<br />
/* standard read/write functions */<br />
#define DDRREAD _IOR(RTDM_CLASS_GPIO,0,char)<br />
#define DDRWRITE _IOW(RTDM_CLASS_GPIO,0,char)<br />
#define DATAREAD _IOR(RTDM_CLASS_GPIO,1,char)<br />
#define DATAWRITE _IOW(RTDM_CLASS_GPIO,1,char)<br />
#define INDEXREAD _IOR(RTDM_CLASS_GPIO,2,char)<br />
#define INDEXWRITE _IOW(RTDM_CLASS_GPIO,2,char)<br />
<br />
/* nolock functions */<br />
#define DDRREAD_NL _IOR(RTDM_CLASS_GPIO, 3, char)<br />
#define DDRWRITE_NL _IOW(RTDM_CLASS_GPIO, 3, char)<br />
#define DATAREAD_NL _IOR(RTDM_CLASS_GPIO, 4, char)<br />
#define DATAWRITE_NL _IOW(RTDM_CLASS_GPIO, 4, char)<br />
#define INDEXREAD_NL _IOR(RTDM_CLASS_GPIO, 5, char)<br />
#define INDEXWRITE_NL _IOW(RTDM_CLASS_GPIO, 5, char)<br />
<br />
/* lock/unlock */<br />
#define GPIOLOCK _IO( RTDM_CLASS_GPIO, 6)<br />
#define GPIOUNLOCK _IO( RTDM_CLASS_GPIO, 7)<br />
<br />
#define DATAREADQ _IOR(RTDM_CLASS_GPIO, 8, char)<br />
#define GETNOTIFY _IOR(RTDM_CLASS_GPIO, 9, char)<br />
#define SETNOTIFY _IOW(RTDM_CLASS_GPIO, 10, char)<br />
#define GETQUEUESIZE _IOR(RTDM_CLASS_GPIO, 11, char)<br />
<br />
#endif /*GPIO_CHAR_H_*/<br />
</syntaxhighlight><br />
<br />
== Kernel Driver Implementation ==<br />
<br />
The EMAC GPIO Class makes it easy to add new devices to the kernel. Function pointers are used to define the implementation of the read and write functions for <code>data</code>, <code>ddr</code>, and <code>index</code> members. This allows for an efficient definition of custom implementations. Standard read and write functions for accessing memory addresses are defined for use in case they match the needs of the interface. This section describes the process of creating and registering an EMAC GPIO Class device in the Linux kernel.<br />
<br />
=== EMAC GPIO Class Definition ===<br />
<br />
The EMAC GPIO Class is implemented in several important files. First, the <code>gpio.h</code> header file defines the structures used for the GPIO class. This file is located in <code>include/linux/class/gpio.h</code> in the kernel source. It defines the following types:<br />
<syntaxhighlight lang=c><br />
typedef u32 gpio_data;<br />
<br />
typedef struct gpio_s {<br />
const char *name;<br />
int subclass;<br />
gpio_data index;<br />
gpio_data range;<br />
void *ddr;<br />
void *data;<br />
gpio_data shadow;<br />
gpio_data(*data_read) (struct gpio_s * gpio);<br />
int (*data_write) (struct gpio_s * gpio, gpio_data data);<br />
gpio_data(*ddr_read) (struct gpio_s * gpio);<br />
int (*ddr_write) (struct gpio_s * gpio, gpio_data data);<br />
gpio_data(*index_read) (struct gpio_s * gpio);<br />
int (*index_write) (struct gpio_s * gpio, gpio_data data);<br />
struct mutex lock;<br />
struct gpio_irq_data irq_data;<br />
} gpio_t;<br />
<br />
struct gpio_irq_data {<br />
int irq;<br />
unsigned int irq_flags;<br />
gpio_data (*handler)(struct gpio_s *gpio);<br />
gpio_data (*get_queue)(struct gpio_s *gpio, gpio_data notify);<br />
void (*irq_config)(struct gpio_s *gpio);<br />
void (*change_notify)(struct gpio_s *gpio, gpio_data curr_notify,<br />
gpio_data new_notify);<br />
};<br />
</syntaxhighlight><br />
<br />
The <code>struct gpio_s</code> structure is the main GPIO device definition. The <code>data_read</code>, <code>data_write</code>, <code>ddr_read</code>, <code>ddr_write</code>, <code>index_read</code>, and <code>index_write</code> function pointers define the low-level actions that are performed when the device is accessed. The <code>struct gpio_irq_data</code> structure is used only for IRQ-enabled GPIO devices as required for the asynchronous notification feature.<br />
In addition, standard low-level functions are declared for use in accessing 8-bit ports. These functions utilize the <code>ioread8</code> and <code>iowrite8</code> functions for accessing the memory locations associated with the device.<br />
<br />
<syntaxhighlight lang=c><br />
/* Write functions */<br />
int gpio_ddr_write8(gpio_t *gpio, gpio_data data);<br />
int gpio_data_write8(gpio_t *gpio, gpio_data data);<br />
int gpio_index_write(gpio_t *gpio, gpio_data data);<br />
int gpio_empty_write(gpio_t *gpio, gpio_data data);<br />
<br />
/* Read functions */<br />
gpio_data gpio_ddr_read8(gpio_t *gpio);<br />
gpio_data gpio_data_read8(gpio_t *gpio);<br />
gpio_data gpio_index_read(gpio_t *gpio);<br />
gpio_data gpio_shadow_read8(gpio_t *gpio);<br />
gpio_data gpio_ff_read(gpio_t *gpio);<br />
gpio_data gpio_zero_read(gpio_t *gpio);<br />
</syntaxhighlight><br />
<br />
Additional functions are provided for registering GPIO devices in the kernel. These will be discussed in the example implementation below.<br />
<br />
The EMAC GPIO Class is implemented in the file <code>drivers/misc/classes/gpio.c</code> in the kernel source tree. This file implements the functions described above as declared in <code>gpio.h</code> and provides the implementation for the <code>sysfs</code> interface. More detailed information can be obtained by reviewing the source code.<br />
<br />
The character driver interface for the EMAC GPIO Class is defined in <code>drivers/misc/classes/char/gpio_char.c</code>. This file provides the <code>ioctl</code> interface, character device registration, and asynchronous notification support. All GPIO class devices create a character device interface upon registration.<br />
<br />
=== Example GPIO Devices ===<br />
<br />
GPIO class devices may be defined and registered at any location in the kernel code. Often times, these devices are hardware-specific and are initialized in the machine initialization code. The example code in this section defines an EMAC GPIO Class device that is used to control several GPIO lines on an AT91-family processor. This code is implemented in a separate C file and initialized from the board-specific implementation.<br />
<br />
The GPIO device in this example is named <code>ege</code> (EMAC GPIO Example). The following variables and setup functions are defined.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
* static array defining GPIO set<br />
*/<br />
static unsigned ege_gpio_set[] = {<br />
AT91_PIN_PC0,<br />
AT91_PIN_PC1,<br />
AT91_PIN_PC2,<br />
AT91_PIN_PC3,<br />
AT91_PIN_PB0,<br />
AT91_PIN_PB1,<br />
AT91_PIN_PB2,<br />
AT91_PIN_PB3,<br />
};<br />
<br />
#define EGE_NUM_GPIO ARRAY_SIZE(ege_gpio_set)<br />
<br />
gpio_data ddr_value_shadow = 0x0;<br />
<br />
/**<br />
* function to initialize the digital inputs and outputs<br />
*/<br />
static int ege_gpio_init(void)<br />
{<br />
int i;<br />
<br />
/* <br />
* set all GPIOs to inputs by default <br />
*/<br />
for (i = 0; i < EGE_NUM_GPIO; i++)<br />
at91_set_gpio_input(ege_gpio_set[i], 0);<br />
<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Each value in the <code>ege_gpio_set</code> array represents one bit in the GPIO device <code>data</code> register. Reading or writing bit 0 will access <code>AT91_PIN_PC0</code> on the processor, while bit 7 will access <code>AT91_PIN_PB3</code>. The <code>ege_gpio_init()</code> function is required to initialize all of the GPIO pins to inputs prior to the first access.<br />
<br />
The first step in creating the GPIO class device is defining the access functions for the <code>data</code>, <code>ddr</code>, and <code>index</code> members. This device will not use an <code>index</code> member, so the <code>index_write</code> and <code>index_read</code> variables will be set to NULL. This prevents them from being registered with the device. There will be no <code>index</code> file created for the <code>sysfs</code> interface, and attempting to access the <code>index</code> through the character interface <code>ioctl</code> will return an error. The <code>ege_gpio_data_read</code>, <code>ege_gpio_data_write</code>, <code>ege_gpio_ddr_read</code>, and <code>ege_gpio_ddr_write</code> functions are defined as follows:<br />
<syntaxhighlight lang=c><br />
/**<br />
* function to read the current value of each GPIO line<br />
*/<br />
static gpio_data ege_gpio_data_read(struct gpio_s *gpio)<br />
{<br />
gpio_data value;<br />
int i;<br />
<br />
value = 0;<br />
for (i = 0; i < EGE_NUM_GPIO; i++)<br />
value |= (at91_get_gpio_value(ege_gpio_set[i]) << i);<br />
<br />
return value;<br />
}<br />
<br />
/**<br />
* function to set the value of the GPIO lines<br />
*/<br />
static int ege_gpio_data_write(struct gpio_s *gpio, gpio_data data)<br />
{<br />
int i;<br />
<br />
for (i = 0; i < EGE_NUM_GPIO; i++) <br />
at91_set_gpio_value(ege_gpio_set[i], (data >> i) & 1);<br />
<br />
return 0;<br />
}<br />
<br />
/**<br />
* data direction configuration read<br />
*/<br />
static gpio_data ege_gpio_ddr_read(struct gpio_s *gpio)<br />
{<br />
return ddr_value_shadow;<br />
}<br />
<br />
/**<br />
* data direction configuration write<br />
*/<br />
static int ege_gpio_ddr_write(struct gpio_s *gpio, gpio_data data)<br />
{<br />
int i;<br />
<br />
ddr_value_shadow = data;<br />
<br />
for (i = 0; i < EGE_NUM_GPIO; i++) {<br />
if(data & (1 << i)) {<br />
/* set to output */<br />
at91_set_gpio_output(ege_gpio_set[i], 0);<br />
at91_set_multi_drive(ege_gpio_set[i], 0);<br />
} else {<br />
/* set to input */<br />
at91_set_gpio_input(ege_gpio_set[i], 0);<br />
}<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Note that the code to read the current <code>ddr</code> configuration of each line is replaced by a shadow value that is stored during the <code>ege_gpio_ddr_write</code> function. After defining these functions, the device must be created and registered. The <code>ege_gpio_class_create</code> function performs this operation and is shown below:<br />
<syntaxhighlight lang=c><br />
struct device *ege_gpio_class_create(void)<br />
{<br />
gpio_t *gpio = kmalloc(sizeof(gpio_t), GFP_KERNEL);<br />
<br />
memset(gpio, 0, sizeof(gpio_t));<br />
gpio->name = "ege_gpio";<br />
gpio->subclass = GPIO_SUBCLASS;<br />
gpio->data_write = ege_gpio_data_write;<br />
gpio->data_read = ege_gpio_data_read;<br />
gpio->ddr_write = ege_gpio_ddr_write;<br />
gpio->ddr_read = ege_gpio_ddr_read;<br />
gpio->index_write = NULL;<br />
gpio->index_read = NULL;<br />
printk("registering gpio device: %s\n", gpio->name);<br />
<br />
return gpio_register_device(gpio);<br />
}<br />
</syntaxhighlight><br />
Once the <code>ege_gpio_init</code> function is called followed by the <code>ege_gpio_class_create</code> function, the <code>ege_gpio</code> device will be created and registered with the system.<br />
<br />
==== Adding Asynchronous Notification Support ====<br />
<br />
If required, asynchronous notification support could be added to the <code>ege_gpio</code> device from the example above. This section provides a simple example of the code required to add this feature.<br />
<br />
The <code>irq_data</code> member of the GPIO class device specifies the action to take for asynchronous notification and interrupt handling. The IRQ will be requested, configured, and registered in the GPIO character interface (<code>gpio_char.c</code>) if <code>irq_data</code> is valid.<br />
<br />
<br />
===== The <code>handler</code> Function Pointer =====<br />
<br />
The <code>handler</code> member of <code>irq_data</code> is a function pointer which will be called by the IRQ handler for the generic GPIO class. This will be scheduled in a workqueue from the interrupt handler (outside of interrupt context) and called with the GPIO device lock held. This allows for the feature to be utilized by interfaces, such as those provided by SPI devices, which may sleep during hardware access. The function returns a bit mask which is compared against the notification mask that's set on open devices. This yields the type of hardware event that has occurred.<br />
<br />
<br />
Typically, the <code>handler</code> function would read an interrupt status register from the device associated with the GPIO interface, such as a PLD register. In the most basic form where only one type of interrupt can occur the <code>handler</code> would simply return 1. The example <code>handler</code> function shown below calls a function <code>read_interrupt_status()</code>, the implementation for which is not discussed here.<br />
<syntaxhighlight lang=c><br />
static gpio_data ege_gpio_handler(struct gpio_s *gpio)<br />
{<br />
return read_interrupt_status();<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>get_queue</code> Function Pointer =====<br />
<br />
The <code>get_queue</code> member of <code>irq_data</code> is a function pointer which is called by the GPIO class interface to determine what data to add to the queue. It is called for any file-descriptor matching the notify mask of the interrupt type that has occurred. This function will be called with the device mutex held.<br />
<br />
The most common implementation of this function utilizes the <code>data_read</code> function of the associated device and stores the current value. This is useful for capturing the current hardware state as instantaneously as possible after the interrupt occurs but before the userspace process is notified of the event. It may be used for other purposes, however, such as taking a timestamp or reading a different hardware register.<br />
<br />
The current notify mask returned by <code>handler</code> will be passed to the <code>get_queue</code> function, so it is possible to customize the action based on the type of event(s) that occurred. The <code>get_queue</code> function shown below reads the current value as returned by <code>data_read</code>.<br />
<syntaxhighlight lang=c><br />
static gpio_data ege_gpio_get_queue(struct gpio_s *gpio, gpio_data notify)<br />
{<br />
return atomic_gpio_data_read(gpio);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>irq_config</code> Function Pointer =====<br />
<br />
The <code>irq_config</code> member of <code>irq_data</code> is a function pointer called by the GPIO class interface before calling <code>request_irq</code>. The purpose of this function is to configure and enable the interrupt in the associated hardware for the GPIO device. In many cases, this function will have few tasks to perform.<br />
<br />
In the example <code>irq_config</code> function shown below, the <code>set_irq_wake()</code> function is called to note that the interrupt should be allowed to wake the hardware from APM suspend mode.<br />
<syntaxhighlight lang=c><br />
static void ege_gpio_irq_config(struct gpio_s *gpio)<br />
{<br />
set_irq_wake(gpio->irq_data.irq, 1);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>change_notify</code> Function Pointer =====<br />
<br />
The <code>change_notify</code> member of <code>irq_data</code> is a function pointer used to make any changes to the hardware when the user interface changes the notification mask. This may or may not be necessary depending on the desired operation.<br />
<br />
The primary function for which this is defined is to keep track of which types of interrupts should be enabled and disabled in the associated hardware. For example, if no file-descriptors are registered for notification on a certain type of event, the associated bit should be disabled in the interrupt enable register. The bit should be enabled in the interrupt enable register as soon as one or more file-descriptors are setup to be notified on this type of event. The current notify mask for the file-descriptor, as well as the new notify mask, will be passed as arguments so that <code>change_notify</code> can determine which bits have been altered. The function for this example interface does nothing.<br />
<syntaxhighlight lang=c><br />
static void ege_gpio_change_notify(struct gpio_s *gpio, gpio_data curr_notify, <br />
gpio_data new_notify)<br />
{<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>irq_data</code> Structure =====<br />
<br />
The final step for adding IRQ handling and asynchronous notification to the interface is to specify the <code>irq_data</code> structure as part of the device initialization. The <code>irq</code> and <code>irq_flags</code> members are used to denote the specific interrupt and its associated features. The updated <code>ege_gpio_class_create</code> function is as follows:<br />
<syntaxhighlight lang=c><br />
struct device *ege_gpio_class_create(void)<br />
{<br />
gpio_t *gpio = kmalloc(sizeof(gpio_t), GFP_KERNEL);<br />
memset(gpio, 0, sizeof(gpio_t));<br />
<br />
gpio->name = "ege_gpio";<br />
gpio->subclass = GPIO_SUBCLASS;<br />
gpio->data_write = ege_gpio_data_write;<br />
gpio->data_read = ege_gpio_data_read;<br />
gpio->ddr_write = ege_gpio_ddr_write;<br />
gpio->ddr_read = ege_gpio_ddr_read;<br />
gpio->index_write = NULL;<br />
gpio->index_read = NULL;<br />
<br />
gpio->irq_data.irq = AT91SAM9260_ID_IRQ1;<br />
gpio->irq_data.irq_flags = IRQF_SHARED | IRQF_TRIGGER_RISING;<br />
gpio->irq_data.handler = ege_gpio_handler;<br />
gpio->irq_data.get_queue = ege_gpio_get_queue;<br />
gpio->irq_data.irq_config = ege_gpio_irq_config;<br />
gpio->irq_data.change_notify = ege_gpio_change_notify;<br />
<br />
printk("registering gpio device: %s\n", gpio->name);<br />
<br />
return gpio_register_device(gpio);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== Summary =====<br />
<br />
After adding the code above, the EMAC GPIO Class driver will register, enable, and handle the interrupt exactly as specified. Notification can be enabled for userspace processes according to the [[#Asynchronous_Notification_Example|Asynchronous Notification Example]].<br />
<br />
<!--[[Category:Custom Development]]--></div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3245Custom Linux Kernel Development2014-01-25T15:50:05Z<p>Tstratman: fixed source code</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio_class_create();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \<br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Using_the_EMAC_GPIO_Class&diff=3244Using the EMAC GPIO Class2014-01-25T14:19:40Z<p>Tstratman: /* EMAC GPIO Class Definition */ fixed code formatting</p>
<hr />
<div>{{todo|Final Draft; List related hardware eventually; (12.17.13-18:20->KY+);(12.18.13-19:00->MD+);(12.19.13-11:21->MW+);(01.14.14-14:20->KY-);(01.15.14-14:00->KY+);(01.16.14-14:00->MD+)|Klint Youngmeyer|project=oe 4, oe 5,mw,ky,FinalDraft,md,ts}}<br />
<br />
The EMAC GPIO Class is a generic programming interface for General Purpose Input Output (GPIO) devices in the Linux Kernel. The GPIO class driver has two main interfaces under standard Linux: Linux sysfs and character device. The GPIO class is extremely flexible and uses a set of function pointers at the kernel level to allow for specialized read/write functions for each device. EMAC utilizes the GPIO class to create devices that use the same simple interface, such as GPIO registers, simple configuration variables, hardware registers, and Analog-to-Digital converter drivers where the user needs to retrieve a single value from the device.<br />
<br />
==Supported Devices==<br />
Most of EMAC's ARM based SOM-Carrier combinations and some of EMAC's x86 boards support the EMAC GPIO Class. For a list of GPIOs on each device, please see the EMAC website at [http://emacinc.com/products/system_on_module emacinc.com/products/system_on_module].<br />
<br />
==Components==<br />
<br />
An EMAC GPIO Class Device has three main components. A clear understanding of these components is important for proper use and implementation.<br />
<br />
===Data===<br />
<br />
The <code>data</code> member of a GPIO device is the primary component. In the most simple devices, this is the only component accessible from userspace. The <code>data</code> member is read and/or written to access or set the current value of the GPIO device. The actual function of the <code>data</code> member is implementation specific. For a GPIO device in its purest form, such as the GPIO ports present in many of EMAC's CPLD designs, the <code>data</code> member is a register value with each of the 8 least significant bits representing the digital state of a single line in the GPIO port. In contrast, A/D devices implemented with the EMAC GPIO Class will typically provide the analog value of the currently selected channel in the <code>data</code> member.<br />
<br />
The <code>data</code> member is allocated as a 32-bit unsigned integer regardless of implementation. Many devices use only the least significant byte or the least significant bit. <br />
<!--Data Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int data;<br />
int output = 42;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will write the contents of the variable 'output' to /dev/portc<br />
if (ioctl(fd_out, DATAWRITE, &output)<0){<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will read the digital value of /dev/portb to the the variable 'data' <br />
if (ioctl(fd_out, DATAREAD, &data)<0)<br />
{<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===DDR===<br />
<br />
The <code>ddr</code> or Data Direction Register is a member of the EMAC GPIO Class that is used primarily for direction-configurable GPIO devices. Many devices do not register this aspect of the interface. The <code>ddr</code> member is used to determine if a particular device should act as an input or output. Depending on the implementation, many devices are bit-configurable GPIO devices, meaning that each bit/line in the GPIO device can be configured as an input or output by its respective value in the <code>ddr</code>. Typically, a '1' value in the <code>ddr</code> configures the device as an output and a '0' value in the ddr configures the device as an input. Bidirectional GPIO devices are generally configured as inputs by default until explicitly configured as an output to prevent hardware contention.<br />
<br />
For example, an EMAC GPIO Class device porta is a one-byte bit-configurable bidirectional GPIO device. Each bit in the <code>data</code> register corresponds to the digital status of the corresponding line porta[0-7]. On reset, the <code>ddr</code> member is read at <code>0x00</code>, indicating that the device is configured with all lines as inputs. If the <code>ddr</code> member is set to <code>0xAA</code> (binary 1010 1010) bits 0, 2, 4, and 6 will remain configured as inputs while the rest of the bits will be configured as outputs. Reading and setting the value in the <code>data</code> member will react according to the configuration set in the <code>ddr</code>. The <code>ddr</code> is allocated as a 32-bit unsigned integer regardless of implementation.<br />
<!--DDR Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int input = 0x00;<br />
int output = 0xff;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will set the data direction of /dev/portc to all outputs as denoted by output=0xff<br />
if (ioctl(fd_out, DDRWRITE, &output)<0)<br />
{<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_in = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will set the data direction of /dev/portb to all inputs as denoted by input=0x00<br />
if (ioctl(fd_out, DDRWRITE, &input)<0)<br />
{<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===Index===<br />
<br />
Many EMAC GPIO Class devices are implemented as indexed GPIO Devices. These devices utilize a member named <code>index</code> which impacts the device according to the implementation. The <code>index</code> member is typically used to specify a memory offset from some base for the <code>data</code> member or some type of channel setting or controller selection. Many devices ignore the <code>index</code> value or do not register this member at all.<br />
<br />
An example of an indexed GPIO Class device is the <code>indexed_atod</code> device (and other A/D devices) found on many EMAC boards. In this case, the <code>index</code> member is used to set the current channel of the A/D to read from the <code>data</code> member. When the <code>index</code> is set to 0, channel 0 will be accessed. When the index is set to 3, the <code>data</code> register will reflect the current value on channel 3 of the device. Another example would be two identical counter registers in a device where setting the index would control which counter was accessed when reading the <code>data</code> register. This would be an alternative to registering a separate device for each counter.<br />
<br />
Indexed GPIO devices should check the applicable range for the <code>index</code> when the user attempts to set the device. For example, an 8-channel A/D device implemented as an EMAC GPIO Class device would have a valid range for the <code>index</code> member of 0-7. Attempting to set the <code>index</code> to anything greater than 7 would cause the <code>index</code> to be set to the maximum allowed value of 7.<br />
<!--Index Code Example:<br />
<syntaxhighlight lang=C><br />
#include "gpio_char.h"<br />
â‹®<br />
int fd_out, fd_in;<br />
int index_c = 1;<br />
int index_b;<br />
<br />
//Open device "/dev/portc" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portc", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portc\n");return -1;<br />
}<br />
//This will set the AtoD index for /dev/portc<br />
if (ioctl(fd_out, INDEXWRITE, &index_c)<0)<br />
{<br />
fprintf(stderr,"error setting index: %s\n", strerror(errno));<br />
return -1;<br />
}<br />
<br />
//Open device "/dev/portb" for reading and writing<br />
//Note that this operation uses the 'open()' Linux system call rather than 'fopen()'<br />
if ((fd_out = open("/dev/portb", O_RDWR)) <= 0){<br />
printf("couldn't open /dev/portb\n");return -1;<br />
}<br />
//This will read the AtoD index for /dev/portb into index_b<br />
if (ioctl(fd_out, INDEXREAD, &index_b)<0)<br />
{<br />
fprintf(stderr,"error reading index: %s\n", strerror(errno));<br />
return -1;<br />
}<br />
â‹®<br />
</syntaxhighlight>--><br />
<br />
===Lock===<br />
<br />
{{imbox | type = notice | text = '''Note:''' Locking support is currently not available on all EMAC boards. This feature was introduced in the later versions of the 2.6.28 kernel for the AT91-based boards. It will be implemented in other kernel trees in the future.}}<br />
<br />
<br />
Many GPIO devices may be accessed by multiple processes simultaneously, which leads to the possibility of race conditions. The EMAC GPIO Class includes a locking mechanism to prevent these cases when used correctly. Without the locking mechanism, synchronization needs to be performed in userspace.<br />
<br />
The lock is implemented as a <code>struct mutex</code> in the GPIO Class device structure. The lock is obtained by the GPIO driver interface through a call to <code>mutex_lock()</code> and freed using <code>mutex_unlock()</code>. This means that any attempts to lock an already locked device will cause the caller to sleep until the lock is freed by the process holding the lock. A nonblocking method using <code>mutex_trylock()</code> may be implemented in the future.<br />
<br />
All access to a device must be synchronized using the lock. Further details on this implementation are described in later sections.<br />
<br />
==User Interfaces==<br />
<br />
This section describes the two user interfaces available for the GPIO class. The sysfs layer is very handy for scripting and testing. For higher performance and more flexible access, the character driver interface is used, generally from a C application. This provides a simple <code>ioctl()</code> interface.<br />
<br />
=== Sysfs ===<br />
The <code>sysfs</code> filesystem is a virtual filesystem provided by the Linux kernel that allows for a file-based interface to kernel driver parameters. The EMAC GPIO Class utilizes <code>sysfs</code> to provide a simple read/write interface to the GPIO Class device. This interface is easily accessible from the Linux shell and through shell scripting.<br />
<br />
The GPIO Class driver registers a directory at <code>/sys/class/gpio</code> assuming that sysfs has been mounted on the system. Under this directory, every GPIO Class device registered with the system will have a directory (i.e. <code>/sys/class/gpio/porta</code>). Within this directory, there will be some files that are a part of the sysfs heirarchy as well as the GPIO Class interface files <code>data</code>, <code>ddr</code>, and <code>index</code>. Depending on the type of device and its implementation, the <code>ddr</code> and <code>index</code> files may or may not exist; <code>data</code> should always be present.<br />
<br />
<br />
{{imbox | text = '''Note:''' The <code>/sys/class/gpio</code> directory is used by the new I/O driver code in the standard Linux kernel tree. This location will be changed by EMAC in the near future to avoid conflict.}}<br />
<br />
==== Reading ====<br />
<br />
Reading the current value of a device's settings is as simple as reading the respective file. The <code>cat</code> command is typically used for this. The output is formatted as ASCII hexadecimal characters. For example, to read the value of the data member of the <code>porta</code> device, run the command: <br />
<br />
<syntaxhighlight lang=console><br />
emac-oe$ cat /sys/class/gpio/porta/data<br />
</syntaxhighlight><br />
<br />
The implementation of the read function for the <code>data</code>, <code>ddr</code>, and <code>index</code> members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The actual value returned depends on the device implementation.<br />
<br />
==== Writing ====<br />
<br />
Writing a new setting to a member of the GPIO device through the sysfs interface is accomplished by writing a new value to the respective file. The <code>echo</code> command is typically used along with file redirection to set the new value directly, although the output of any command could be used as long as it is formatted correctly. For example, to set the <code>porta</code> device to <code>0xFF</code> (all on) the user would first set all bits to output using the <code>ddr</code> register and then write <code>0xFF</code> to the data register as shown below: <br />
<br />
<syntaxhighlight lang=console><br />
emac-oe$ echo 0xff > /sys/class/gpio/porta/ddr<br />
emac-oe$ echo 0xff > /sys/class/gpio/porta/data<br />
</syntaxhighlight><br />
<br />
The implementation of the write function for the <code>data</code>, <code>ddr</code>, and <code>index</code> members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The low-level effects of the write function depends on the device implementation.<br />
<br />
=== Character Driver ===<br />
<br />
The character driver interface is the preferred method for accessing EMAC GPIO Class devices from programmed applications. This interface is significantly more efficient than the sysfs layer and easier to program. In kernels that support the GPIO Class locking mechanism, the character driver interface offers user control over the lock that is not available using the sysfs interface. The character driver interface uses the <code>ioctl()</code> system call. Newer kernels also support an <code>fasync</code> method for signal-based event notification from the driver to the user application.<br />
<br />
==== Available IOCTLs ====<br />
<br />
Several different <code>ioctl</code> commands are available for use. The user must know the supported features of the device before using an <code>ioctl</code> command. For example, many devices do not support the <code>ddr</code> or <code>index</code> functionality. All <code>ioctl</code> commands will return a negative error code on failure.<br />
<br />
===== Locking =====<br />
The ioctl commands in this section will acquire and free the GPIO lock on kernels that include support for the lock. These commands are the most efficient to use when a single GPIO read/write is required. On kernels that do not support the GPIO lock, these commands simply perform the advertised action. For commands which read a value, the ioctl will store the value read into a 32-bit integer which is passed to it via a pointer. For commands which write a value, the ioctl takes a pointer to the 32-bit integer which holds the value to be written.<br />
<br />
* <code>DATAREAD</code>: Read the current value of the device's <code>data</code> member by calling the <code>data_read</code> function.<br />
* <code>DATAWRITE</code>: Write a new value to the device's <code>data</code> member by calling the <code>data_write</code> function.<br />
* <code>DDRREAD</code>: Read the current value of the device's <code>ddr</code> member by calling the <code>ddr_read</code> function.<br />
* <code>DDRWRITE</code>: Write a new value to the device's <code>ddr</code> member by calling the <code>ddr_write</code> function.<br />
* <code>INDEXREAD</code>: Read the current value of the device's <code>index</code> member by calling the <code>index_read</code> function.<br />
* <code>INDEXWRITE</code>: Write a new value to the device's <code>index</code> member by calling the <code>index_write</code> function.<br />
<br />
===== Lock Control =====<br />
The ioctl commands in this section are only available on kernels that support the GPIO Class locking mechanism. They are used to control the current state of the lock.<br />
<br />
* <code>GPIOLOCK</code>: Lock the device's mutex through a call to <code>mutex_lock()</code>. This command will sleep until the lock has been acquired.<br />
* <code>GPIOUNLOCK</code>: Release the device's mutex through a call to <code>mutex_unlock()</code>. This command should not be called unless the lock has already been acquired using <code>GPIOLOCK</code>.<br />
<br />
===== No-Lock =====<br />
The ioctl commands in this section do not affect the lock of the GPIO device and are only available in kernels which support the GPIO Class locking feature. These are lock-free versions of the standard commands listed in the [[#Locking|Locking]] section. Before calling one of these commands, the process must acquire the lock using the <code>GPIOLOCK</code> command. These commands allow synchronization between multiple processes or threads when accessing the same device. For example, when performing a read followed by a write, the lock would need to be held for the duration of both commands to ensure that incorrect values are not written to the device. These commands can also be used to provide higher performance when writing and/or reading several values in a batch; the lock should be acquired before the batch and released afterwards.<br />
<br />
* <code>DATAREAD_NL</code>: Read the current value of the device's <code>data</code> member.<br />
* <code>DATAWRITE_NL</code>: Write a new value to the device's <code>data</code> member.<br />
* <code>DDRREAD_NL</code>: Read the current value of the device's <code>ddr</code> member.<br />
* <code>DDRWRITE_NL</code>: Write a new value to the device's <code>ddr</code> member.<br />
* <code>INDEXREAD_NL</code> the current value of the device's <code>index</code> member.<br />
* <code>INDEXWRITE_NL</code>: Write a new value to the device's <code>index</code> member.<br />
<br />
===== Asynchronous Notification =====<br />
The ioctl commands in this section are for use with the asynchronous notification feature of the EMAC GPIO Class. Most devices do not use this feature, and these commands are only available on kernels that support this feature. The low-level implementation is device-specific.<br />
<br />
* <code>SETNOTIFY</code>: Set a new notification bitmask for the current file descriptor. The value is passed to the ioctl call as a pointer to a 32-bit integer. The gpio lock is acquired and released during this command.<br />
<br />
For the following commands, the value is returned via a pointer to a 32-bit integer passed to the ioctl call. The gpio lock is not acquired and does not need to be held for these commands.<br />
* <code>GETNOTIFY</code>: Get the current notification bitmask for this file descriptor.<br />
* <code>DATAREADQ</code>: Read the first value from the data queue.<br />
* <code>GETQUEUESIZE</code>: Read the current number of values in the data queue for this file descriptor.<br />
<br />
==== Programming ====<br />
<br />
The following general examples demonstrate the character driver programming interface. <br />
<br />
<br />
{{imbox | type=content| text=The examples below do not check the return value of calls for errors. Be sure to check for and handle errors in a production system.}}<br />
<br />
<br />
To access a device from a C application, it must first be opened using ''open()'': <br />
<syntaxhighlight lang=c><br />
int fd;<br />
fd = open(DEVICE, O_RDWR);<br />
...<br />
close(fd);<br />
</syntaxhighlight><br />
<br />
If the open command is successful, any supported ioctl command may be used to access the device. The example below sets the value of the ''data'' member to 0xFF<br />
<br />
<syntaxhighlight lang=c><br />
__u32 arg;<br />
...<br />
arg = 0xff;<br />
ioctl(fd, DATAWRITE, &arg);<br />
</syntaxhighlight><br />
<br />
The example below uses the locking mechanism to perform a sequence of accesses to a device:<br />
<syntaxhighlight lang=c><br />
#define CONTROLBIT (1 << 3)<br />
__u32 arg;<br />
...<br />
ioctl(fd, GPIOLOCK, NULL);<br />
arg = 1;<br />
ioctl(fd, INDEXWRITE_NL, &arg);<br />
ioctl(fd, DATAREAD_NL, &arg);<br />
/* set control bit */<br />
arg &= CONTROLBIT;<br />
ioctl(fd, DATAWRITE_NL, &arg);<br />
ioctl(fd, GPIOUNLOCK, NULL);<br />
</syntaxhighlight><br />
<br />
==== Asynchronous Notification Example ====<br />
<br />
Asynchronous notification for the EMAC GPIO Class is a new feature available in some kernels. This was added to the driver at the same time as locking support and utilizes the <code>fasync</code> system call. Essentially, this feature allows the kernel driver to notify the user application of some event through a signal. Typically this is used for devices which support hardware interrupts. Currently, no standard EMAC devices utilize the asynchronous notification feature.<br />
<br />
For each open file descriptor of a certain device, it is possible to set a notification mask indicating which types of events will trigger notification as well as which signal will be sent to the process from the driver. The default signal is <code>SIGIO</code>. When an event occurs, a value will be written to a queue for each file descriptor that is registered for notification of the event. The notification mask, events, and queue functionality are all implementation-specific.<br />
<br />
The following example utilizes the asynchronous notification interface for a device that supports it. This particular device is an interrupt-enabled register that will notify a process if the type of interrupt that occurs matches the notification mask of the particular file descriptor. When an applicable interrupt occurs, the data register will immediately be queued into the file descriptor specific data queue.<br />
<br />
<br />
{{imbox | text='''Note:''' The device utilized in the example below is an example device which does not exist on any EMAC system. The example is provided to illustrate the asynchronous notification interface which may be available on a system for a real device.}}<br />
<br />
<br />
=====gpio-fasync-example.c=====<br />
<syntaxhighlight lang=c><br />
#define _GNU_SOURCE<br />
<br />
#include <fcntl.h><br />
#include <sys/types.h><br />
#include <sys/stat.h><br />
#include <sys/ioctl.h><br />
#include <stdio.h><br />
#include <stdlib.h><br />
#include <unistd.h><br />
#include <asm/types.h><br />
#include <signal.h><br />
#include "gpio_char.h"<br />
<br />
static sig_atomic_t caught = 0;<br />
static sig_atomic_t run = 1;<br />
<br />
void sig_handle(int sig)<br />
{<br />
if (sig == SIGIO)<br />
caught = 1;<br />
else /* termination */<br />
run = 0;<br />
}<br />
<br />
#define DEVICE "/dev/gpio_async"<br />
#define NOTIFY_MASK (1 << 4)<br />
<br />
/**<br />
* function to enable asynchronous notification on the given file descriptor<br />
* for the specified signal<br />
* @param fd the open GPIO device file descriptor to enable notification for<br />
* @param sig the signal to be sent by the kernel for event notification<br />
*/<br />
static void set_fasync(int fd, int sig);<br />
<br />
/**<br />
* function to set the event notification flags for the driver on a given <br />
* file descriptor.<br />
* @param fd the open GPIO device file descriptor for notification<br />
* @param notify bitmask specifying which events this file descriptor should<br />
* be notified on<br />
* @return the result of the ioctl() call to set the notification flags<br />
*/<br />
static int set_notify_flags(int fd, __u32 notify);<br />
<br />
/**<br />
* function to get the queue size for the given file descriptor<br />
* @param fd the open GPIO device file descriptor to query<br />
* @return the current queue size as reported by the driver<br />
*/<br />
static __u32 get_queue_size(int fd);<br />
<br />
int main(int argc, char *argv[]){<br />
<br />
int fd;<br />
__u32 data;<br />
struct sigaction sact;<br />
sigset_t block_mask;<br />
sigset_t suspend_mask;<br />
sigset_t old_mask;<br />
<br />
/* set up signal handlers */<br />
sact.sa_handler = sig_handle;<br />
sigemptyset(&sact.sa_mask);<br />
sact.sa_flags = 0;<br />
sigaction(SIGIO, &sact, NULL);<br />
sigaction(SIGTERM, &sact, NULL);<br />
sigaction(SIGINT, &sact, NULL);<br />
<br />
/* Open all devices */<br />
if ((fd = open(DEVICE, O_RDWR)) <= 0) {<br />
fprintf(stderr, "Error on open %s\n", DEVICE);<br />
exit(EXIT_FAILURE);<br />
}<br />
<br />
/* allow sigsuspend to be interrupted by any signal */<br />
sigemptyset(&suspend_mask);<br />
<br />
/* <br />
* note that it is advantageous to mask all requested signals at<br />
* this point until all configuration is completed at which point<br />
* they will be unmasked by sigsuspend(). This also makes sense for<br />
* the implementation here, as the signals will be blocked again after<br />
* sigsuspend() returns during the DATAREADQ calls, preventing race<br />
* conditions. The call to sigprocmask() below does this.<br />
*/<br />
sigemptyset(&block_mask);<br />
sigaddset(&block_mask, SIGIO);<br />
<br />
sigprocmask(SIG_BLOCK, &block_mask, &old_mask);<br />
<br />
/* enable fasync notification on device */<br />
set_fasync(fd, SIGIO);<br />
<br />
/* Inform the driver which flags each fd should be notified on */<br />
set_notify_flags(fd, NOTIFY_MASK);<br />
<br />
printf("Waiting for signals\n");<br />
fflush(stdout);<br />
<br />
while (run) {<br />
sigsuspend(&suspend_mask);<br />
if (caught) {<br />
while (get_queue_size(fd) > 0) {<br />
ioctl(fd, DATAREADQ, &data);<br />
printf("Queued value 0x%X\n", data);<br />
caught = 0;<br />
}<br />
}<br />
}<br />
<br />
printf("Terminating...\n");<br />
close(fd);<br />
<br />
exit(EXIT_SUCCESS);<br />
}<br />
<br />
static void set_fasync(int fd, int sig)<br />
{<br />
int flags;<br />
<br />
flags = fcntl(fd, F_GETFL);<br />
flags |= FASYNC;<br />
/* set owner... tells who to send the signal to */<br />
/* <br />
* note that in a threaded application, getpid() should be replaced<br />
* with getid()<br />
*/<br />
fcntl(fd, F_SETOWN, getpid());<br />
fcntl(fd, F_SETSIG, sig);<br />
/* Now that configuration is complete, set FASYNC mode */<br />
fcntl(fd, F_SETFL, flags);<br />
}<br />
<br />
static int set_notify_flags(int fd, __u32 notify)<br />
{<br />
return ioctl(fd, SETNOTIFY, &notify);<br />
}<br />
<br />
static __u32 get_queue_size(int fd)<br />
{<br />
__u32 data;<br />
<br />
ioctl(fd, GETQUEUESIZE, &data);<br />
return data;<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
=====gpio_char.h=====<br />
<syntaxhighlight lang=c><br />
#ifndef GPIO_CHAR_H_<br />
#define GPIO_CHAR_H_<br />
<br />
/* Userspace version of kernel header file */<br />
<br />
#include <linux/ioctl.h><br />
<br />
#define RTDM_CLASS_GPIO 0x80 <br />
<br />
/* standard read/write functions */<br />
#define DDRREAD _IOR(RTDM_CLASS_GPIO,0,char)<br />
#define DDRWRITE _IOW(RTDM_CLASS_GPIO,0,char)<br />
#define DATAREAD _IOR(RTDM_CLASS_GPIO,1,char)<br />
#define DATAWRITE _IOW(RTDM_CLASS_GPIO,1,char)<br />
#define INDEXREAD _IOR(RTDM_CLASS_GPIO,2,char)<br />
#define INDEXWRITE _IOW(RTDM_CLASS_GPIO,2,char)<br />
<br />
/* nolock functions */<br />
#define DDRREAD_NL _IOR(RTDM_CLASS_GPIO, 3, char)<br />
#define DDRWRITE_NL _IOW(RTDM_CLASS_GPIO, 3, char)<br />
#define DATAREAD_NL _IOR(RTDM_CLASS_GPIO, 4, char)<br />
#define DATAWRITE_NL _IOW(RTDM_CLASS_GPIO, 4, char)<br />
#define INDEXREAD_NL _IOR(RTDM_CLASS_GPIO, 5, char)<br />
#define INDEXWRITE_NL _IOW(RTDM_CLASS_GPIO, 5, char)<br />
<br />
/* lock/unlock */<br />
#define GPIOLOCK _IO( RTDM_CLASS_GPIO, 6)<br />
#define GPIOUNLOCK _IO( RTDM_CLASS_GPIO, 7)<br />
<br />
#define DATAREADQ _IOR(RTDM_CLASS_GPIO, 8, char)<br />
#define GETNOTIFY _IOR(RTDM_CLASS_GPIO, 9, char)<br />
#define SETNOTIFY _IOW(RTDM_CLASS_GPIO, 10, char)<br />
#define GETQUEUESIZE _IOR(RTDM_CLASS_GPIO, 11, char)<br />
<br />
#endif /*GPIO_CHAR_H_*/<br />
</syntaxhighlight><br />
<br />
== Kernel Driver Implementation ==<br />
<br />
The EMAC GPIO Class makes it easy to add new devices to the kernel. Function pointers are used to define the implementation of the read and write functions for <code>data</code>, <code>ddr</code>, and <code>index</code> members. This allows for an efficient definition of custom implementations. Standard read and write functions for accessing memory addresses are defined for use in case they match the needs of the interface. This section describes the process of creating and registering an EMAC GPIO Class device in the Linux kernel.<br />
<br />
=== EMAC GPIO Class Definition ===<br />
<br />
The EMAC GPIO Class is implemented in several important files. First, the <code>gpio.h</code> header file defines the structures used for the GPIO class. This file is located in <code>include/linux/class/gpio.h</code> in the kernel source. It defines the following types:<br />
<syntaxhighlight lang=c><br />
typedef u32 gpio_data;<br />
<br />
typedef struct gpio_s {<br />
const char *name;<br />
int subclass;<br />
gpio_data index;<br />
gpio_data range;<br />
void *ddr;<br />
void *data;<br />
gpio_data shadow;<br />
gpio_data(*data_read) (struct gpio_s * gpio);<br />
int (*data_write) (struct gpio_s * gpio, gpio_data data);<br />
gpio_data(*ddr_read) (struct gpio_s * gpio);<br />
int (*ddr_write) (struct gpio_s * gpio, gpio_data data);<br />
gpio_data(*index_read) (struct gpio_s * gpio);<br />
int (*index_write) (struct gpio_s * gpio, gpio_data data);<br />
struct mutex lock;<br />
struct gpio_irq_data irq_data;<br />
} gpio_t;<br />
<br />
struct gpio_irq_data {<br />
int irq;<br />
unsigned int irq_flags;<br />
gpio_data (*handler)(struct gpio_s *gpio);<br />
gpio_data (*get_queue)(struct gpio_s *gpio, gpio_data notify);<br />
void (*irq_config)(struct gpio_s *gpio);<br />
void (*change_notify)(struct gpio_s *gpio, gpio_data curr_notify,<br />
gpio_data new_notify);<br />
};<br />
</syntaxhighlight><br />
<br />
The <code>struct gpio_s</code> structure is the main GPIO device definition. The <code>data_read</code>, <code>data_write</code>, <code>ddr_read</code>, <code>ddr_write</code>, <code>index_read</code>, and <code>index_write</code> function pointers define the low-level actions that are performed when the device is accessed. The <code>struct gpio_irq_data</code> structure is used only for IRQ-enabled GPIO devices as required for the asynchronous notification feature.<br />
In addition, standard low-level functions are declared for use in accessing 8-bit ports. These functions utilize the <code>ioread8</code> and <code>iowrite8</code> functions for accessing the memory locations associated with the device.<br />
<br />
<syntaxhighlight lang=c><br />
/* Write functions */<br />
int gpio_ddr_write8(gpio_t *gpio, gpio_data data);<br />
int gpio_data_write8(gpio_t *gpio, gpio_data data);<br />
int gpio_index_write(gpio_t *gpio, gpio_data data);<br />
int gpio_empty_write(gpio_t *gpio, gpio_data data);<br />
<br />
/* Read functions */<br />
gpio_data gpio_ddr_read8(gpio_t *gpio);<br />
gpio_data gpio_data_read8(gpio_t *gpio);<br />
gpio_data gpio_index_read(gpio_t *gpio);<br />
gpio_data gpio_shadow_read8(gpio_t *gpio);<br />
gpio_data gpio_ff_read(gpio_t *gpio);<br />
gpio_data gpio_zero_read(gpio_t *gpio);<br />
</syntaxhighlight><br />
<br />
Additional functions are provided for registering GPIO devices in the kernel. These will be discussed in the example implementation below.<br />
<br />
The EMAC GPIO Class is implemented in the file <code>drivers/misc/classes/gpio.c</code> in the kernel source tree. This file implements the functions described above as declared in <code>gpio.h</code> and provides the implementation for the <code>sysfs</code> interface. More detailed information can be obtained by reviewing the source code.<br />
<br />
The character driver interface for the EMAC GPIO Class is defined in <code>drivers/misc/classes/char/gpio_char.c</code>. This file provides the <code>ioctl</code> interface, character device registration, and asynchronous notification support. All GPIO class devices create a character device interface upon registration.<br />
<br />
=== Example GPIO Devices ===<br />
<br />
GPIO class devices may be defined and registered at any location in the kernel code. Often times, these devices are hardware-specific and are initialized in the machine initialization code. The example code in this section defines an EMAC GPIO Class device that is used to control several GPIO lines on an AT91-family processor. This code is implemented in a separate C file and initialized from the board-specific implementation.<br />
<br />
The GPIO device in this example is named <code>ege</code> (EMAC GPIO Example). The following variables and setup functions are defined.<br />
<br />
<syntaxhighlight lang=c><br />
/**<br />
* static array defining GPIO set<br />
*/<br />
static unsigned ege_gpio_set[] = {<br />
AT91_PIN_PC0,<br />
AT91_PIN_PC1,<br />
AT91_PIN_PC2,<br />
AT91_PIN_PC3,<br />
AT91_PIN_PB0,<br />
AT91_PIN_PB1,<br />
AT91_PIN_PB2,<br />
AT91_PIN_PB3,<br />
};<br />
<br />
#define EGE_NUM_GPIO ARRAY_SIZE(ege_gpio_set)<br />
<br />
gpio_data ddr_value_shadow = 0x0;<br />
<br />
/**<br />
* function to initialize the digital inputs and outputs<br />
*/<br />
static int ege_gpio_init(void)<br />
{<br />
int i;<br />
<br />
/* <br />
* set all GPIOs to inputs by default <br />
*/<br />
for (i = 0; i < EGE_NUM_GPIO; i++)<br />
at91_set_gpio_input(ege_gpio_set[i], 0);<br />
<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Each value in the <code>ege_gpio_set</code> array represents one bit in the GPIO device <code>data</code> register. Reading or writing bit 0 will access <code>AT91_PIN_PC0</code> on the processor, while bit 7 will access <code>AT91_PIN_PB3</code>. The <code>ege_gpio_init()</code> function is required to initialize all of the GPIO pins to inputs prior to the first access.<br />
<br />
The first step in creating the GPIO class device is defining the access functions for the <code>data</code>, <code>ddr</code>, and <code>index</code> members. This device will not use an <code>index</code> member, so the <code>index_write</code> and <code>index_read</code> variables will be set to NULL. This prevents them from being registered with the device. There will be no <code>index</code> file created for the <code>sysfs</code> interface, and attempting to access the <code>index</code> through the character interface <code>ioctl</code> will return an error. The <code>ege_gpio_data_read</code>, <code>ege_gpio_data_write</code>, <code>ege_gpio_ddr_read</code>, and <code>ege_gpio_ddr_write</code> functions are defined as follows:<br />
<syntaxhighlight lang=c><br />
/**<br />
* function to read the current value of each GPIO line<br />
*/<br />
static gpio_data ege_gpio_data_read(struct gpio_s *gpio)<br />
{<br />
gpio_data value;<br />
int i;<br />
<br />
value = 0;<br />
for (i = 0; i < EGE_NUM_GPIO; i++)<br />
value |= (at91_get_gpio_value(ege_gpio_set[i]) << i);<br />
<br />
return value;<br />
}<br />
<br />
/**<br />
* function to set the value of the GPIO lines<br />
*/<br />
static int ege_gpio_data_write(struct gpio_s *gpio, gpio_data data)<br />
{<br />
int i;<br />
<br />
for (i = 0; i < EGE_NUM_GPIO; i++) <br />
at91_set_gpio_value(ege_gpio_set[i], (data >> i) & 1);<br />
<br />
return 0;<br />
}<br />
<br />
/**<br />
* data direction configuration read<br />
*/<br />
static gpio_data ege_gpio_ddr_read(struct gpio_s *gpio)<br />
{<br />
return ddr_value_shadow;<br />
}<br />
<br />
/**<br />
* data direction configuration write<br />
*/<br />
static int ege_gpio_ddr_write(struct gpio_s *gpio, gpio_data data)<br />
{<br />
int i;<br />
<br />
ddr_value_shadow = data;<br />
<br />
for (i = 0; i < EGE_NUM_GPIO; i++) {<br />
if(data & (1 << i)) {<br />
/* set to output */<br />
at91_set_gpio_output(ege_gpio_set[i], 0);<br />
at91_set_multi_drive(ege_gpio_set[i], 0);<br />
} else {<br />
/* set to input */<br />
at91_set_gpio_input(ege_gpio_set[i], 0);<br />
}<br />
}<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
Note that the code to read the current <code>ddr</code> configuration of each line is replaced by a shadow value that is stored during the <code>ege_gpio_ddr_write</code> function. After defining these functions, the device must be created and registered. The <code>ege_gpio_class_create</code> function performs this operation and is shown below:<br />
<syntaxhighlight lang=c><br />
struct device *ege_gpio_class_create(void)<br />
{<br />
gpio_t *gpio = kmalloc(sizeof(gpio_t), GFP_KERNEL);<br />
<br />
memset(gpio, 0, sizeof(gpio_t));<br />
gpio->name = "ege_gpio";<br />
gpio->subclass = GPIO_SUBCLASS;<br />
gpio->data_write = ege_gpio_data_write;<br />
gpio->data_read = ege_gpio_data_read;<br />
gpio->ddr_write = ege_gpio_ddr_write;<br />
gpio->ddr_read = ege_gpio_ddr_read;<br />
gpio->index_write = NULL;<br />
gpio->index_read = NULL;<br />
printk("registering gpio device: %s\n", gpio->name);<br />
<br />
return gpio_register_device(gpio);<br />
}<br />
</syntaxhighlight><br />
Once the <code>ege_gpio_init</code> function is called followed by the <code>ege_gpio_class_create</code> function, the <code>ege_gpio</code> device will be created and registered with the system.<br />
<br />
==== Adding Asynchronous Notification Support ====<br />
<br />
If required, asynchronous notification support could be added to the <code>ege_gpio</code> device from the example above. This section provides a simple example of the code required to add this feature.<br />
<br />
The <code>irq_data</code> member of the GPIO class device specifies the action to take for asynchronous notification and interrupt handling. The IRQ will be requested, configured, and registered in the GPIO character interface (<code>gpio_char.c</code>) if <code>irq_data</code> is valid.<br />
<br />
<br />
===== The <code>handler</code> Function Pointer =====<br />
<br />
The <code>handler</code> member of <code>irq_data</code> is a function pointer which will be called by the IRQ handler for the generic GPIO class. This will be scheduled in a workqueue from the interrupt handler (outside of interrupt context) and called with the GPIO device lock held. This allows for the feature to be utilized by interfaces, such as those provided by SPI devices, which may sleep during hardware access. The function returns a bit mask which is compared against the notification mask that's set on open devices. This yields the type of hardware event that has occurred.<br />
<br />
<br />
Typically, the <code>handler</code> function would read an interrupt status register from the device associated with the GPIO interface, such as a PLD register. In the most basic form where only one type of interrupt can occur the <code>handler</code> would simply return 1. The example <code>handler</code> function shown below calls a function <code>read_interrupt_status()</code>, the implementation for which is not discussed here.<br />
<syntaxhighlight lang=c><br />
static gpio_data ege_gpio_handler(struct gpio_s *gpio)<br />
{<br />
return read_interrupt_status();<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>get_queue</code> Function Pointer =====<br />
<br />
The <code>get_queue</code> member of <code>irq_data</code> is a function pointer which is called by the GPIO class interface to determine what data to add to the queue. It is called for any file-descriptor matching the notify mask of the interrupt type that has occurred. This function will be called with the device mutex held.<br />
<br />
The most common implementation of this function utilizes the <code>data_read</code> function of the associated device and stores the current value. This is useful for capturing the current hardware state as instantaneously as possible after the interrupt occurs but before the userspace process is notified of the event. It may be used for other purposes, however, such as taking a timestamp or reading a different hardware register.<br />
<br />
The current notify mask returned by <code>handler</code> will be passed to the <code>get_queue</code> function, so it is possible to customize the action based on the type of event(s) that occurred. The <code>get_queue</code> function shown below reads the current value as returned by <code>data_read</code>.<br />
<syntaxhighlight lang=c><br />
static gpio_data ege_gpio_get_queue(struct gpio_s *gpio, gpio_data notify)<br />
{<br />
return atomic_gpio_data_read(gpio);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>irq_config</code> Function Pointer =====<br />
<br />
The <code>irq_config</code> member of <code>irq_data</code> is a function pointer called by the GPIO class interface before calling <code>request_irq</code>. The purpose of this function is to configure and enable the interrupt in the associated hardware for the GPIO device. In many cases, this function will have few tasks to perform.<br />
<br />
In the example <code>irq_config</code> function shown below, the <code>set_irq_wake()</code> function is called to note that the interrupt should be allowed to wake the hardware from APM suspend mode.<br />
<syntaxhighlight lang=c><br />
static void ege_gpio_irq_config(struct gpio_s *gpio)<br />
{<br />
set_irq_wake(gpio->irq_data.irq, 1);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>change_notify</code> Function Pointer =====<br />
<br />
The <code>change_notify</code> member of <code>irq_data</code> is a function pointer used to make any changes to the hardware when the user interface changes the notification mask. This may or may not be necessary depending on the desired operation.<br />
<br />
The primary function for which this is defined is to keep track of which types of interrupts should be enabled and disabled in the associated hardware. For example, if no file-descriptors are registered for notification on a certain type of event, the associated bit should be disabled in the interrupt enable register. The bit should be enabled in the interrupt enable register as soon as one or more file-descriptors are setup to be notified on this type of event. The current notify mask for the file-descriptor, as well as the new notify mask, will be passed as arguments so that <code>change_notify</code> can determine which bits have been altered. The function for this example interface does nothing.<br />
<syntaxhighlight lang=c><br />
static void ege_gpio_change_notify(struct gpio_s *gpio, gpio_data curr_notify, <br />
gpio_data new_notify)<br />
{<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== The <code>irq_data</code> Structure =====<br />
<br />
The final step for adding IRQ handling and asynchronous notification to the interface is to specify the <code>irq_data</code> structure as part of the device initialization. The <code>irq</code> and <code>irq_flags</code> members are used to denote the specific interrupt and its associated features. The updated <code>ege_gpio_class_create</code> function is as follows:<br />
<syntaxhighlight lang=c><br />
struct device *ege_gpio_class_create(void)<br />
{<br />
gpio_t *gpio = kmalloc(sizeof(gpio_t), GFP_KERNEL);<br />
memset(gpio, 0, sizeof(gpio_t));<br />
<br />
gpio->name = "ege_gpio";<br />
gpio->subclass = GPIO_SUBCLASS;<br />
gpio->data_write = ege_gpio_data_write;<br />
gpio->data_read = ege_gpio_data_read;<br />
gpio->ddr_write = ege_gpio_ddr_write;<br />
gpio->ddr_read = ege_gpio_ddr_read;<br />
gpio->index_write = NULL;<br />
gpio->index_read = NULL;<br />
<br />
gpio->irq_data.irq = AT91SAM9260_ID_IRQ1;<br />
gpio->irq_data.irq_flags = IRQF_SHARED | IRQF_TRIGGER_RISING;<br />
gpio->irq_data.handler = ege_gpio_handler;<br />
gpio->irq_data.get_queue = ege_gpio_get_queue;<br />
gpio->irq_data.irq_config = ege_gpio_irq_config;<br />
gpio->irq_data.change_notify = ege_gpio_change_notify;<br />
<br />
printk("registering gpio device: %s\n", gpio->name);<br />
<br />
return gpio_register_device(gpio);<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
===== Summary =====<br />
<br />
After adding the code above, the EMAC GPIO Class driver will register, enable, and handle the interrupt exactly as specified. Notification can be enabled for userspace processes according to the [[#Asynchronous_Notification_Example|Asynchronous Notification Example]].<br />
<br />
<!--[[Category:Custom Development]]--></div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3243Custom Linux Kernel Development2014-01-25T13:33:24Z<p>Tstratman: 8 revisions: Imported from old wikidev</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3242Custom Linux Kernel Development2014-01-21T13:04:52Z<p>Tstratman: testing</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Testing ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment]] above, compile the kernel and load it to your target hardware. Test all functionality, particularly new devices that were added to the carrier board support file, and make adjustments as necessary.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3241Custom Linux Kernel Development2014-01-21T12:58:30Z<p>Tstratman: compilation</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
==== Building and Deployment ====<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Compiling ===<br />
After making the development changes required to support a new carrier board, you must change the kernel configuration to specify the new carrier board. Using the menu configuration utility described in the [[#Menuconfig|Menuconfig section]], navigate to 'System Type -> Atmel AT91 System-on-Chip -> EMAC Carrier Board Selection''. The list should now have a choice for ''NPD Carrier Support''. Highlight this option and press enter. Finally, exit and save the configuration.<br />
<br />
Following the steps described in [[#Building and Deployment]] above, compile the kernel and <br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3240Custom Linux Kernel Development2014-01-17T13:21:20Z<p>Tstratman: section heading only...</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
=== Compiling ===<br />
After making the development changes required to support a new carrier board, DO SOME CRAZY STUFF TO COMPILE IT.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3239Custom Linux Kernel Development2014-01-17T12:56:44Z<p>Tstratman: /* SPI Support */ removed extra ifdef</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3238Custom Linux Kernel Development2014-01-17T12:55:30Z<p>Tstratman: /* Licensing */ fixed link</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
#endif<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3237Custom Linux Kernel Development2014-01-15T13:44:31Z<p>Tstratman: added final carrier code</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
#endif<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code is as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
</syntaxhighlight><br />
<br />
===== Boardspec =====<br />
The EMAC <code>boardspec</code> platform driver is used to specify board specific initialization code, such as GPIO class devices. A function pointer is passed into the platform device structure for the driver and called when the driver is loaded. <code>carrier_classes()</code> is utilized in this case as seen below.<br />
<syntaxhighlight lang="c"><br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
<br />
static struct platform_device boardspec_device = {<br />
.name = "boardspec",<br />
.id = 2,<br />
.dev = {<br />
.platform_data = &carrier_classes,<br />
},<br />
};<br />
<br />
static inline void carrier_device_boardspec(void)<br />
{<br />
at91_set_gpio_output(AT91_PIN_PE1, 1); /* LCD Enable */<br />
platform_device_register(&boardspec_device);<br />
}<br />
</syntaxhighlight><br />
<br />
===== Carrier Initialization =====<br />
The final function in the carrier board specification file is <code>carrier_init()</code>. This function is called from the SoM board file and initializes the <code>carrier_spec</code> structure. This includes setting the <code>use_periph</code> mask value to denote which devices are supported as well as initializing function pointers and other data specific to this carrier definition. The code from the <code>board-som210.c</code> file may be used without modification to support the NPD board. This code is listed below.<br />
<syntaxhighlight lang="c"><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3236Custom Linux Kernel Development2014-01-15T13:26:37Z<p>Tstratman: updated gpio code</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
#endif<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code would be as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
/* SD card power switch */<br />
static unsigned sdsw_gpio_set[] = { AT91_PIN_PD10 };<br />
<br />
static unsigned sdsw_direction = 0x01; /* output */<br />
static unsigned sdsw_value = 0x00; /* low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(sdsw)<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* SOM GPIO11 */<br />
AT91_PIN_PB15, /* SOM GPIO12 */<br />
AT91_PIN_PB16, /* SOM GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
sdsw_gpio();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
/* Analog mux */<br />
amux_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
<br />
<br />
<br />
<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3235Custom Linux Kernel Development2014-01-14T13:22:26Z<p>Tstratman: added GPIO code</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
===== SPI Support =====<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
#endif<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
===== Programmable Clocks =====<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
===== GPIO Support =====<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The following GPIO class devices are included in the SoM-210ES carrier support code:<br />
# <code>sdsw</code> creates a GPIO device for toggling power to the SD card on the carrier board<br />
# <code>gpio</code> creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header<br />
# <code>rs232_4xx</code> controls the serial port configuration lines on the carrier board<br />
# <code>beeper</code> creates a method to toggle the input line to the beeper on the carrier board<br />
<br />
Assume that the NPD hardware requires the <code>sdsw</code> and <code>rs232_4xx</code> features, but does not have the beeper or generic "Handy" GPIO header. Instead, a 3:8 analog multiplexer is provided on the SoM lines GPIO11, GPIO12, and GPIO13, which correspond to CPU pins PB14, PB15, and PB16 (see the SoM-9G45M manual). The resulting GPIO support code would be as follows:<br />
<syntaxhighlight lang="c"><br />
<br />
static int sdsw_write(struct gpio_s *gpio,gpio_data data)<br />
{<br />
at91_set_gpio_value(AT91_PIN_PD10,(char)data);<br />
return 0;<br />
}<br />
<br />
static gpio_data sdsw_read(struct gpio_s *gpio)<br />
{<br />
return at91_get_gpio_value(AT91_PIN_PD10);<br />
}<br />
<br />
static inline struct device *som210_sdsw(void)<br />
{<br />
gpio_t *gpio = kmalloc(sizeof(gpio_t),GFP_KERNEL);<br />
memset(gpio,0,sizeof(gpio_t));<br />
<br />
at91_set_gpio_output(AT91_PIN_PD10, 0);<br />
<br />
gpio->name = "sdsw";<br />
gpio->subclass = GPIO_SUBCLASS;<br />
gpio->data_write = sdsw_write;<br />
gpio->data_read = sdsw_read;<br />
printk("registering gpio device: %s\n",gpio->name);<br />
return gpio_register_device(gpio);<br />
}<br />
<br />
/* Analog mux control */<br />
static unsigned amux_gpio_set[] = {<br />
AT91_PIN_PB14, /* GPIO11 */<br />
AT91_PIN_PB15, /* GPIO12 */<br />
AT91_PIN_PB16, /* GPIO13 */<br />
};<br />
<br />
static unsigned amux_direction = 0x0F; /* Default: All outputs */<br />
static unsigned amux_value = 0x00; /* Default: Output low */<br />
<br />
GPIO_SET_FUNCTION_CREATE(amux)<br />
<br />
static unsigned rs232_4xx_gpio_set[] = {<br />
AT91_PIN_PB24,<br />
AT91_PIN_PB25,<br />
AT91_PIN_PE0,<br />
};<br />
<br />
static unsigned rs232_4xx_direction = 0x07;<br />
static unsigned rs232_4xx_value = 0x01; /* Default to RS232 */<br />
<br />
GPIO_SET_FUNCTION_CREATE(rs232_4xx)<br />
<br />
/*<br />
* Boardspec IOEX<br />
*/<br />
static int carrier_classes(void)<br />
{<br />
/* SD Power */<br />
som210_sdsw();<br />
<br />
/* RS-232/422/485 Control */<br />
rs232_4xx_gpio_class_create();<br />
<br />
beeper_gpio_class_create();<br />
gpio_gpio_class_create();<br />
<br />
return 0;<br />
}<br />
</syntaxhighlight><br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3197Custom Linux Kernel Development2014-01-13T13:17:12Z<p>Tstratman: additional carrier board code</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
The next section in the carrier board file specifies the SPI devices on the system. Assume that the NPD carrier board will have support for the CS4271 audio codec and one spare general purpose SPI software interface. The AD7766 SPI device in the SoM210ES carrier board file will not be required. The resulting SPI specification is as follows:<br />
<syntaxhighlight lang="c"><br />
static struct spi_s spi0cs1 = <br />
{<br />
.name = "spi0cs1",<br />
.subclass = 0,<br />
.tip = lsi2esc_spi_tip,<br />
.xmit = lsi2esc_spi_xmit,<br />
.confwrite = lsi2esc_spi_confwrite,<br />
.confread = lsi2esc_spi_confread,<br />
.speedread = lsi2esc_spi_speedread,<br />
.speedwrite = lsi2esc_spi_speedwrite,<br />
.gpio_name = NULL,<br />
.gpio_create = NULL,<br />
.gpio_data = NULL,<br />
};<br />
<br />
static struct spi_board_info carrier_spi_devices[] = {<br />
#if defined(CONFIG_SND_SOC_CS4271) || defined(CONFIG_SND_SOC_CS4271_MODULE)<br />
{ /* CS4271 codec */<br />
.modalias = "cs4271",<br />
.chip_select = 2,<br />
.bus_num = 1,<br />
.max_speed_hz = 1 * 1000 * 1000,<br />
},<br />
#endif<br />
{ /* SPI0 CS1 (Spare) */<br />
.modalias = "lsi2esc",<br />
.chip_select = 1,<br />
.controller_data = (void *)AT91_PIN_PD28,<br />
.bus_num = 0,<br />
.max_speed_hz = 1e6,<br />
.platform_data = &spi0cs1,<br />
},<br />
#endif<br />
};<br />
<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=Note that the <code>spi0cs1</code> device is an EMAC SPI Class device. See [[EMAC SPI Programming]] for more information on how to utilize this interface.}}<br />
<br />
The next function in the carrier board file is <code>set_tc_clocks()</code>, which configures the timer/counter blocks for constant frequency clock outputs on the two dedicated clock output pins on the module. If these are not required for the hardware design, they may be disabled. Assume that the NPD board does not utilize these clocks and remove the function from the file altogether.<br />
<br />
The next section of the carrier board support file sets up GPIO devices using the [[Using the EMAC GPIO Class|EMAC GPIO Class]]. This involves setting up a collection of functions and arrays for each GPIO device and using the <code>GPIO_SET_FUNCTION_CREATE()</code> macro as defined in <code>gpio-wrapper.h</code> to define a complete GPIO class device. The first device listed, <code>sdsw</code>, creates a GPIO device for toggling power to the SD card on the carrier board. The <code>gpio</code> GPIO class device creates a generic device using the lines labeled ''Handy'' GPIO pins on the SoM210ES header. The <code>rs232_4xx</code> device controls the serial port configuration lines on the carrier board.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3196Custom Linux Kernel Development2014-01-08T13:18:03Z<p>Tstratman: carrier modifications</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support Files ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. For the purposes of this example, assume that the name of the product is "NPD." Start by copying the <code>emac-carrier/board-som210.c</code> file to <code>emac-carrier/board-npd.c</code> and follow the steps below to add support to the kernel for this new board. <br />
<syntaxhighlight lang=console><br />
developer@ldc:~/linux/arch/arm/mach-at91/emac-carrier$ cp board-som210.c board-npd.c<br />
</syntaxhighlight><br />
<br />
==== Kconfig and Makefile Additions ====<br />
An entry must be added to the <code>Kconfig</code> file in order for it to be an available option in the configuration menu. To do this, edit <code>emac-carrier/Kconfig</code> and add the entry as shown below under the ''EMAC Carrier Board Selection'' selection menu.<br />
<syntaxhighlight lang="make" highlight="6,7"><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
<br />
config NPD_CARRIER<br />
bool "NPD Carrier Support"<br />
<br />
....<br />
endchoice<br />
</syntaxhighlight><br />
<br />
A corresponding Makefile entry is required to trigger compilation and linking of the <code>board-npd.c</code> file that was created when the <code>CONFIG_NPD_CARRIER</code> option is selected. Add the following line to <code>emac-carrier/Makefile</code>:<br />
<syntaxhighlight lang="make"><br />
obj-$(CONFIG_NPD_CARRIER) += board-npd.o<br />
</syntaxhighlight><br />
<br />
==== Source Code Modifications ====<br />
The final step in adding support for the NPD carrier board involves modifying the C source in the <code>emac-carrier/board-npd.c</code> file that was created to match the hardware. As this is a fictional product, the modifications below will make assumptions as to what features are included.<br />
<br />
===== Serial Support =====<br />
The <code>carrier_map_io()</code> function performs initialization and mapping of the serial ports on the system. The SOM210 carrier has three serial ports using the DBGU, USART1, and USART2 controllers. Assume that the NPD system has one additional serial port mapped to USART3 on the CPU with no handshaking. The resulting code is shown below.<br />
<syntaxhighlight lang="c" highlight="8"><br />
static void __init carrier_map_io(void)<br />
{<br />
/* DGBU on ttyS0. (Rx & Tx only) */<br />
at91_register_uart(0, 0, 0);<br />
<br />
at91_register_uart(AT91SAM9G45_ID_US1, 1, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US2, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);<br />
at91_register_uart(AT91SAM9G45_ID_US3, 3, 0);<br />
<br />
/* set serial console to ttyS0 (ie, DBGU) */<br />
at91_set_serial_console(0);<br />
}<br />
</syntaxhighlight><br />
<br />
Create new SoM carrier file using this as demo.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3193Custom Linux Kernel Development2014-01-07T13:17:11Z<p>Tstratman: more carrier info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a New Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
=== Machine-Specific Support Files ===<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
=== Carrier Board-Specific Support ===<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
=== Example New Carrier Board Support File ===<br />
Suppose that support for a new carrier board is required and utilizes hardware very similar to the SoM-210ES. <br />
<br />
Create new SoM carrier file using this as demo.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3192Custom Linux Kernel Development2014-01-07T13:03:12Z<p>Tstratman: more carrier info</p>
<hr />
<div>{{todo|InProgress|Travis Stratman|project=oe 5,TS,InProgress}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added. The carrier support functions and definitions are included through <code>arch/arm/mach-at91/include/mach/emac-carrier.h</code>.<br />
<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Taking SOM-210ES as an example, look at the <code>board-som210.c</code>. You will see a good portion of software that is very similar to the full board support files in the <code>mach-at91</code> directory, since this file defines all peripheral support required by the carrier board hardware not included in the base code for the SoM itself. At the bottom of the file, you will find the <code>carrier_init()</code> function, which is called from the SoM initialization code and sets up the <code>carrier_spec</code> struct. This function is shown below for review:<br />
<syntaxhighlight lang=c><br />
int __init carrier_init(struct carrier_spec *spec)<br />
{<br />
spec->use_periph = CARRIER_USES_USBH | CARRIER_USES_MCI | \<br />
CARRIER_USES_TSADCC | CARRIER_USES_PWM | \<br />
CARRIER_USES_LCD | CARRIER_USES_SPI | \ <br />
CARRIER_USES_I2C0;<br />
<br />
spec->carrier_map_io = carrier_map_io;<br />
spec->carrier_boardspec = carrier_device_boardspec;<br />
spec->carrier_spi_info = carrier_spi_devices;<br />
spec->carrier_spi_cnt = ARRAY_SIZE(carrier_spi_devices);<br />
<br />
return 0;<br />
<br />
}<br />
</syntaxhighlight><br />
Note that some of the <code>carrier_spec</code> parameters are function pointers, such as <code>spec->carrier_map_io</code> and <code>spec->carrier_boardspec</code>.<br />
<br />
<br />
<br />
Create new SoM carrier file using this as demo.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=3166Custom Linux Kernel Development2014-01-06T13:16:15Z<p>Tstratman: added more on carrier board support</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added.<br />
<br />
The <code>emac-carrier</code> directory contains code and configuration specifically for support of EMAC carrier boards. This code is used to generate the carrier specification values used in the <code>board-som9m10g45.c</code> file as shown above. The <code>Kconfig</code> file in the <code>emac-carrier</code> directory is sourced from the <code>mach-at91/Kconfig</code> file and provides selections for all available carrier boards. A snippet of the <code>emac-carrier/Kconfig</code> file is shown below.<br />
<syntaxhighlight lang=make><br />
if MACH_SOM9M10G45<br />
<br />
choice<br />
prompt "EMAC Carrier Board Selection"<br />
....<br />
config SOM200_CARRIER<br />
bool "SOM-200ES Carrier Support"<br />
<br />
config SOM210_CARRIER<br />
bool "SOM-210ES (PPC-E4) Carrier Support"<br />
<br />
config SOM212_CARRIER<br />
bool "SOM-212ES Carrier Support"<br />
<br />
config SOM250_CARRIER<br />
bool "SOM-250ES (PPC-E10/PPC-E7+) Carrier Support"<br />
<br />
endchoice<br />
</syntaxhighlight><br />
<br />
This generates the selection menu discussed in the [[#Menuconfig|Menuconfig section]]. If "SOM-210ES (PPC-E4) Carrier Support" is selected in the menu, the variable <code>CONFIG_SOM210_CARRIER</code> will be defined. Looking at <code>emac-carrier/Makefile</code>, you will see entries for each carrier board as well as other related options. For example, the line below specifies that <code>board-som210.c</code> will be compiled and included in the image if the SOM-210ES carrier support option is selected.<br />
<syntaxhighlight lang=make><br />
obj-$(CONFIG_SOM210_CARRIER) += board-som210.o<br />
</syntaxhighlight><br />
<br />
Look at som210 carrier file.<br />
<br />
Create new SoM carrier file using this as demo.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2981Custom Linux Kernel Development2014-01-03T13:45:21Z<p>Tstratman: added outline for carrier board remaining info</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added.<br />
<br />
Look at Kconfig.<br />
Carrier board support in emac-carrier directory.<br />
Look at som210 carrier file.<br />
<br />
Create new SoM carrier file using this as demo.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2854Custom Linux Kernel Development2014-01-02T00:03:25Z<p>Tstratman: /* Adding Support for a new Carrier Board */ file structure info</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
One common kernel development task working with EMAC systems is adding support for a new custom carrier board for use with an EMAC SoM. In general, the procedure for this task is to use one of the existing EMAC carrier board support files as a base and modify as needed to support the custom hardware. Additions to the Makefiles and Kconfig are also generally required to add new selections to the kernel configuration and build system. This section covers an example of the work required for this using the SoM-9G45 module as an example.<br />
<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
Board-level support files are found under the machine-specific directories within the kernel structure for ARM devices. For the Atmel AT91-based devices, this is found under <code>arch/arm/mach-at91</code>. Within this directory, you will see some CPU-specific support and includes, as well as a collection of files prefixed with ''<code>board-</code>''. These files contain configuration and initialization code to support a specific board -- only one of which may be included in a single kernel binary. <br />
<br />
The board support file for the SoM9G45 is <code>board-som9m10g45.c</code>. Looking at this file, you will see that it contains code for devices inherent to the module, such as the flash, LCD, Ethernet PHY, micro-SD (MMC), and others. You will also notice references to the <code>cspec</code> ("carrier specification") structure. This structure is defined by code in the carrier board file and determines which devices are enabled and how they are configured to match the features of the target carrier board.<br />
<br />
{{mbox|type=notice|text=Note that this method of board support configuration changed dramatically in more recent kernel series with the ''Device Tree'' structure.}}<br />
<br />
For example, in the <code>som_board_init()</code> function, SPI support is configured with the following lines:<br />
<syntaxhighlight lang=c><br />
/* SPI */<br />
at91_add_device_spi(som_spi_devices, ARRAY_SIZE(som_spi_devices));<br />
<br />
if (cspec.use_periph & CARRIER_USES_SPI)<br />
at91_add_device_spi(cspec.carrier_spi_info, cspec.carrier_spi_cnt);<br />
</syntaxhighlight><br />
<br />
The first call to <code>at91_add_device_spi()</code> adds devices present on the SoM itself, while the next lines check to see if the carrier board specification indicates that SPI is utilized, and if so the devices in the carrier board spi configuration are added.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2853Custom Linux Kernel Development2014-01-01T23:12:23Z<p>Tstratman: /* Adding Support for a new Carrier Board */ started section</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
{{mbox|type=notice|text=Note that the process described below is somewhat tailored to the 2.6.30-at91 kernel tree and will not be applicable directly to systems which use different kernels without some modification. The intent is to familiarize the task of adding support for a custom carrier board using this as a specific example. Contact EMAC if you require more information on how to do this for your target system.}}<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2852Custom Linux Kernel Development2014-01-01T23:07:37Z<p>Tstratman: /* Menuconfig */ fixed broken link</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Building the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2851Custom Linux Kernel Development2014-01-01T23:05:09Z<p>Tstratman: /* Where to go for Additional Information */ removed note</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2850Custom Linux Kernel Development2014-01-01T23:04:42Z<p>Tstratman: /* Where to go for Additional Information */ added LKN reference</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; ''Linux Kernel in a Nutshell''<br />
: This book is written by Greg Kroah-Hartman, one of the primary developers and maintainers of the kernel and covers the process and tools for building, configuration, and installation of the Linux kernel. It is available for free through [http://www.kroah.com/lkn/ the authors site] in electronic format or in-print through O'Reilly.<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.<br />
<br />
<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2849Custom Linux Kernel Development2014-01-01T22:57:57Z<p>Tstratman: support links</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]<br />
* [http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
There is an abundance of information available both online and in-print on the topic of Linux kernel development. Some of these resources are discussed below.<br />
<br />
; Kernel.org<br />
: Kernel.org is the site hosting the Linux kernel. Source code, news, links, and other helpful information related to the Linux kernel can be found on this site.<br />
; ''Linux Device Drivers, Third Edition'' (LDD3)<br />
: This book is available online in free PDF form through the [http://lwn.net/Kernel/LDD3 LWN.net site]. It is also available in-print through O'Reilly. LDD3 covers most of the topics required for Linux kernel development and includes examples. Note that some of the APIs covered have changed since 2.6.10 when the book was written so adaptation may be required to use the example code.<br />
; Mailing Lists<br />
: There are many very active mailing lists (see http://vger.kernel.org/vger-lists.html) that can be used to ask questions or search through archives for solutions. The archive of the Linux Kernel mailing list is available at [https://lkml.org/ LKML.org] and archives to other lists can be found through a web search as well as links noted in the list [http://vger.kernel.org/vger-lists.html here].<br />
; EMAC Support<br />
: EMAC provides custom Linux kernel development and kernel development support for EMAC customers on a contractual basis. Contact [http://www.emacinc.com/support EMAC Support] for more information.<br />
<br />
<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2848Custom Linux Kernel Development2014-01-01T22:24:28Z<p>Tstratman: changed links</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [[https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]]<br />
* [[http://www.tldp.org/HOWTO/Module-HOWTO/copyright.html | TLDP.org LKM Copyright Article]]<br />
<br />
== Where to go for Additional Information ==<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2847Custom Linux Kernel Development2014-01-01T15:47:28Z<p>Tstratman: links</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [[Open Source Licensing]]<br />
* [http://en.wikipedia.org/wiki/Loadable_kernel_module#License_issues Wikipedia Loadable Kernel Module Article]<br />
* [[https://www.kernel.org/pub/linux/kernel/COPYING Linux Kernel COPYING File]]<br />
* <br />
<br />
<br />
== Where to go for Additional Information ==<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2846Custom Linux Kernel Development2014-01-01T15:28:59Z<p>Tstratman: license info</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
If configuration options are the only customization required for your project, you may continue by [[Building the Linux Kernel#Building the Kernel|building]] the kernel. If only loadable module options were changed from the original configuration that your running kernel was built with, you will only need to load the modules onto the target system as described [[Buiding the Linux Kernel#Loading Kernel Modules|here]]. If other built-in options were modified, you will need to reload the kernel image as well, which requires a different procedure depending on the bootloader. ''' More here links for different bootloaders '''<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
It is important to note that all code built-in to the kernel automatically fall under the the GPLv2 license and must use an Open Source license compatible with the terms of the GPL. For loadable kernel modules, there is controversy over whether modules are derived works of the kernel. While proprietary and other non-GPL-compatible modules are generally permitted, several restrictions apply: The "taint" flag will be set on the kernel as soon as the module is loaded, and certain symbols are only available to modules marked with a GPL-compatible license.<br />
<br />
EMAC recommends that you seek legal advice if you are unsure of the license requirements for your software.<br />
<br />
See the following resources for more information:<br />
* [http://en.wikipedia.org/wiki/Loadable_kernel_module#License_issues Wikipedia Loadable Kernel Module Article]<br />
<br />
<br />
== Where to go for Additional Information ==<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2845Custom Linux Kernel Development2014-01-01T15:00:52Z<p>Tstratman: added image</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. You will be prompted to save the kernel configuration as shown in Figure 2.<br />
[[File:Kernel Config Save Confirm.png|center|thumb|500px|Figure 2: Linux Kernel Menuconfig Save Confirmation]]<br />
<br />
Refer to configuration section in the kernel building document. Show how to add / remove options in the config.<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
<br />
<br />
== Where to go for Additional Information ==<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=File:Kernel_Config_Save_Confirm.png&diff=2844File:Kernel Config Save Confirm.png2014-01-01T15:00:11Z<p>Tstratman: Kernel menuconfig save confirmation dialog</p>
<hr />
<div>Kernel menuconfig save confirmation dialog</div>Tstratmanhttps://wiki.emacinc.com/index.php?title=Custom_Linux_Kernel_Development&diff=2822Custom Linux Kernel Development2013-12-31T23:28:19Z<p>Tstratman: config info</p>
<hr />
<div>{{todo|Write this|Travis Stratman|project=oe 5,TS,NotStarted}}<br />
<br />
The ability to easily customize and expand any portion of the kernel is a feature of Linux that makes it very well suited for embedded systems development. In the embedded environment, specialized hardware, protocols, and systems may require a look into the kernel internals, custom configuration, feature additions, or driver development. This article aims to provide information on the most common kernel development tasks for EMAC OE Linux systems. In addition, the reader is pointed to sources for kernel development resources.<br />
<br />
== Prerequisites ==<br />
<br />
This article assumes some basic familiarity with Linux and C programming competency. Before continuing, make sure that git is installed on your development machine, and review the [[Building the Linux Kernel]] document.<br />
<br />
== Background ==<br />
Maybe some more here about the technical design of the kernel and very brief history... monolithic kernel, loadable modules, etc. For now just see wikipedia http://en.wikipedia.org/wiki/Linux_kernel<br />
<br />
== The Kernel Source ==<br />
<br />
Source code for EMAC kernels is provided through our Git server. Refer to the documentation for your system to determine the correct source to use. <br />
<br />
{{mbox|type=notice|text=For this guide, the 2.6.30-at91 kernel tree will be used, which currently covers many of EMAC's SoM-based ARM products.}}<br />
<br />
=== Clone the Git Repository ===<br />
<br />
To clone the git repository over anonymous HTTP, run the following commands:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ git clone http://git.emacinc.com/public/source/linux-2.6.30-at91.git<br />
</syntaxhighlight><br />
<br />
Once the command has completed, the entire source should be contained in the <code>linux-2.6.30-at91</code> directory. The ''master'' branch will be checked out automatically. Because EMAC uses the ''master'' branch for all releases, this is the correct branch to use, but other branches or tags may be checked out if directed or required.<br />
<br />
=== Kernel Source Structure ===<br />
<br />
Within the kernel source tree that was downloaded, you will see several directories. Table 1 gives a brief description of each of these directories.<br />
{| class="wikitable mw-collapsible"<br />
|-<br />
! Directory name !! Description<br />
|-<br />
| <code>arch</code> || Architecture-specific kernel code with subdirectories for each architecture<br />
|-<br />
| <code>block</code> || Block device driver code<br />
|-<br />
| <code>crypto</code> || Encryption support algorithms<br />
|-<br />
| <code>Documentation</code> || Text documentation files on the kernel and APIs<br />
|-<br />
| <code>drivers</code> || Device driver code, with a subdirectory structure for each device type<br />
|-<br />
| <code>firmware</code> || Code for building firmware required to communicate with devices<br />
|-<br />
| <code>fs</code> || File systems code<br />
|-<br />
| <code>include</code> || Include (header) files required to build the kernel code<br />
|-<br />
| <code>init</code> || Kernel initialization code<br />
|-<br />
| <code>ipc</code> || Interprocess communications code<br />
|-<br />
| <code>kernel</code> || Main internal kernel code<br />
|-<br />
| <code>lib</code> || Library code<br />
|-<br />
| <code>mm</code> || Memory management code<br />
|-<br />
| <code>net</code> || Kernel networking code<br />
|-<br />
| <code>samples</code> || Code examples and drivers that have not been fully developed<br />
|-<br />
| <code>scripts</code> || Various scripts used for the configuration and build process as well as standalone utility scripts<br />
|-<br />
| <code>security</code> || Kernel security support<br />
|-<br />
| <code>sound</code> || Sound and audio driver code<br />
|-<br />
| <code>usr</code> || Code used during kernel image creation<br />
|-<br />
| <code>virt</code> || Virtualization support code<br />
|-<br />
|}<br />
<br />
These directories will be referred to as needed in this document.<br />
<br />
== Configuration ==<br />
<br />
The kernel uses a configuration system that specifies how every aspect of the kernel is built. <br />
<br />
=== Configuration Structure ===<br />
<br />
The kernel configuration is generated based on selections by the user combined with dependency information built into the Kconfig structure. You will find a file named <code>Kconfig</code> in most source directories within the kernel. These files follow the language described in [https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt <code>Documentation/kbuild/kconfig-language.txt</code>] and control the structure and operation of the kernel configuration utility.<br />
<br />
The current kernel configuration is stored in a file named <code>.config</code> in the top level of the kernel source tree. This file is read and updated by the configuration utility and is used by the make system during the build process. The first step in configuring the kernel often involves initializing this file with a default configuration set up with sane values for the target platform. These default configuration files are stored under the <code>arch</code> directory. For example, <code>arch/arm/configs/</code>.<br />
<br />
{{mbox|type=notice|text=Note that the <code>.config</code> file is a hidden file since its filename begins with a <code>'.'</code>. The ''ls'' utility will not show this file by default unless the ''-a'' option is passed to show hidden files.}}<br />
<br />
In this example, copy the <code>arch/arm/configs/som9g45-som210_defconfig</code> file to the top level of the kernel source as <code>.config</code>:<br />
<syntaxhighlight lang=bash><br />
developer@ldc:~$ cp arch/arm/configs/som9g45-som210_defconfig .config<br />
</syntaxhighlight><br />
This is the default configuration file for the EMAC SoM-9G45 module using an SoM-210ES carrier board.<br />
<br />
The configuration file defines all <code>CONFIG</code> values that are set, either ''y'' (yes), ''m'' (module), a numeric value, or a string value. Options not configured are entered into the file as a comment with the option followed by the words "is not set." An example of each of these formats is shown below:<br />
<syntaxhighlight lang=make><br />
#<br />
# Automatically generated make config: don't edit<br />
# Linux kernel version: 2.6.30<br />
# Tue Jan 10 17:42:58 2012<br />
#<br />
CONFIG_ARM=y<br />
CONFIG_SYS_SUPPORTS_APM_EMULATION=y<br />
CONFIG_GENERIC_GPIO=y<br />
CONFIG_GENERIC_TIME=y<br />
CONFIG_GENERIC_CLOCKEVENTS=y<br />
CONFIG_MMU=y<br />
# CONFIG_NO_IOPORT is not set<br />
...<br />
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"<br />
...<br />
CONFIG_INIT_ENV_ARG_LIMIT=32<br />
...<br />
CONFIG_SDIO_UART=m<br />
</syntaxhighlight><br />
<br />
{{mbox|type=notice|text=While editing the configuration file by hand is not recommended because it is easy to break dependencies that the configuration utility will catch, viewing the configuration file as text can be helpful in quickly viewing the current configuration selections.}}<br />
<br />
=== Configuring the Kernel ===<br />
<br />
The kernel supports several methods of generating configuration values including command line utilities, a menu-based utility, a Qt-based utility, and a GTK+-based utility. These utilities are instantiated as <code>make</code> targets. The menu-based utility, invoked by the ''menuconfig'' command is the only option supported by the EMAC Linux kernel build script. See [[Building the Linux Kernel#Configuring the Kernel|here]] for more information on how to initiate the configuration process using the EMAC Linux kernel build script.<br />
<br />
==== Menuconfig ====<br />
<br />
The top-level interface to the kernel menuconfig utility is shown in Figure 1. Note that the navigation keys and legend are shown at the top of the page.<br />
[[File:Kernel Menuconfig.png|center|thumb|500px|Figure 1: Linux Kernel Menuconfig Main Page]]<br />
<br />
Any menu item with a ''--->'' will lead to a submenu with further options. For example, to set the EMAC carrier board used with this SoM, you would use the arrow keys to highlight ''System Type'' and press Enter to select. From this menu, select ''Atmel AT91 System-on-Chip'' followed by ''EMAC Carrier Board Selection''. This will initiate a menu allowing a single selection with all of the carrier boards supported by the currently selected SoM module. If, for example, you wanted to target the SoM-200ES carrier board, you could highlight ''SOM-200ES Carrier Support'' and press the space bar or Enter to select.<br />
<br />
Once all desired changes have been made, select ''Exit'' and press enter from the main menu. <br />
<br />
<br />
Refer to configuration section in the kernel building document. Show how to add / remove options in the config.<br />
<br />
== Adding Support for a new Carrier Board ==<br />
<br />
Show how to add a carrier board in the 2.6.30 "emac-carrier" structure.<br />
<br />
== Driver Development ==<br />
<br />
Basic info on driver structure here.<br />
<br />
== Licensing ==<br />
<br />
<br />
== Where to go for Additional Information ==<br />
<br />
LDD3, mailing list, EMAC support.</div>Tstratman