mirror of
https://github.com/lupyuen/pinephone-nuttx.git
synced 2025-01-13 05:08:32 +08:00
Clean up
This commit is contained in:
parent
9f6fef712e
commit
9bc06bf9ab
1 changed files with 51 additions and 49 deletions
100
README.md
100
README.md
|
@ -175,7 +175,7 @@ The following is a journal that documents the porting of NuttX to PinePhone. It
|
|||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
# Download NuttX
|
||||
# NuttX on QEMU
|
||||
|
||||
[Apache NuttX RTOS](https://nuttx.apache.org/docs/latest/) now runs on Arm Cortex-A53 with Multi-Core SMP...
|
||||
|
||||
|
@ -187,6 +187,8 @@ PinePhone is based on [Allwinner A64 SoC](https://linux-sunxi.org/A64) with 4 Co
|
|||
|
||||
We start with NuttX Mainline, run it on QEMU, then mod it for PinePhone.
|
||||
|
||||
## Download NuttX
|
||||
|
||||
Download the Source Code for NuttX Mainline, which supports Arm Cortex-A53...
|
||||
|
||||
```bash
|
||||
|
@ -216,7 +218,7 @@ Install the Build Prerequisites, skip the RISC-V Toolchain...
|
|||
|
||||
- ["Install Prerequisites"](https://lupyuen.github.io/articles/nuttx#install-prerequisites)
|
||||
|
||||
# Download Toolchain
|
||||
## Download Toolchain
|
||||
|
||||
Download the Arm Toolchain for AArch64 ELF Bare-Metal Target (`aarch64-none-elf`)...
|
||||
|
||||
|
@ -250,7 +252,7 @@ aarch64-none-elf-gcc -v
|
|||
|
||||
[(Based on the instructions here)](https://github.com/apache/incubator-nuttx/tree/master/boards/arm64/qemu/qemu-a53)
|
||||
|
||||
# Download QEMU
|
||||
## Download QEMU
|
||||
|
||||
Download and install QEMU...
|
||||
|
||||
|
@ -262,7 +264,7 @@ For macOS we may use `brew`...
|
|||
brew install qemu
|
||||
```
|
||||
|
||||
# Build NuttX: Single Core
|
||||
## Build NuttX: Single Core
|
||||
|
||||
First we build NuttX for a Single Core of Arm Cortex-A53...
|
||||
|
||||
|
@ -285,7 +287,7 @@ The NuttX Output Files may be found here...
|
|||
|
||||
- [NuttX for Arm Cortex-A53 Single Core](https://github.com/lupyuen/pinephone-nuttx/releases/tag/v1.0.1)
|
||||
|
||||
# Test NuttX with QEMU: Single Core
|
||||
## Test NuttX with QEMU: Single Core
|
||||
|
||||
This is how we test NuttX on QEMU with a Single Core of Arm Cortex-A53...
|
||||
|
||||
|
@ -400,7 +402,7 @@ NuttX is [POSIX Compliant](https://nuttx.apache.org/docs/latest/introduction/inv
|
|||
|
||||
And NuttX runs everything in RAM, no File System needed. (For now)
|
||||
|
||||
# Build NuttX: Multi Core
|
||||
## Build NuttX: Multi Core
|
||||
|
||||
From Single Core to Multi Core! Now we build NuttX for 4 Cores of Arm Cortex-A53...
|
||||
|
||||
|
@ -426,7 +428,7 @@ The NuttX Output Files may be found here...
|
|||
|
||||
- [NuttX for Arm Cortex-A53 Multi-Core](https://github.com/lupyuen/pinephone-nuttx/releases/tag/v1.0.0)
|
||||
|
||||
# Test NuttX with QEMU: Multi Core
|
||||
## Test NuttX with QEMU: Multi Core
|
||||
|
||||
And this is how we test NuttX on QEMU with 4 Cores of Arm Cortex-A53...
|
||||
|
||||
|
@ -535,7 +537,7 @@ We see each of the 4 Cores starting NuttX (CPU0 to CPU3). That's so cool!
|
|||
|
||||
(Can we use QEMU to partially emulate PinePhone? That would be extremely helpful!)
|
||||
|
||||
# Inside NuttX for Cortex-A53
|
||||
## Inside NuttX for Cortex-A53
|
||||
|
||||
Now we browse the Source Files for the implementation of Cortex-A53 on NuttX.
|
||||
|
||||
|
@ -565,7 +567,7 @@ Which implements all kinds of Arm64 Features: [FPU](https://github.com/apache/in
|
|||
|
||||
(We'll reuse them for PinePhone)
|
||||
|
||||
# NuttX Image
|
||||
## NuttX Image
|
||||
|
||||
Next we analyse the NuttX Image with [Ghidra](https://ghidra-sre.org/), to understand the NuttX Image Header and Startup Code.
|
||||
|
||||
|
@ -711,7 +713,7 @@ We'll change this to 0x4008 0000 for PinePhone, since Kernel Start Address is 0x
|
|||
|
||||
We've seen the NuttX Image (which looks like a Linux Kernel Image), let's compare with a PinePhone Linux Kernel Image and see how NuttX needs to be tweaked...
|
||||
|
||||
# PinePhone Image
|
||||
## PinePhone Image
|
||||
|
||||
Will NuttX run on PinePhone? Let's analyse a PinePhone Linux Kernel Image with Ghidra, to look at the Linux Kernel Header and Startup Code.
|
||||
|
||||
|
@ -768,7 +770,7 @@ So we shift `Image` in Ghidra to start at 0x4008 0000...
|
|||
|
||||
![Ghidra with PinePhone Linux Image](https://lupyuen.github.io/images/arm-ghidra3.png)
|
||||
|
||||
# Will NuttX Boot On PinePhone?
|
||||
## Will NuttX Boot On PinePhone?
|
||||
|
||||
_So will NuttX boot on PinePhone?_
|
||||
|
||||
|
@ -1535,7 +1537,7 @@ __Timer IRQ `ARM_ARCH_TIMER_IRQ`__ is defined in [arch/arm64/src/common/arm64_ar
|
|||
#define GIC_NUM_PRI_PER_REG 4
|
||||
```
|
||||
|
||||
# Timer Interrupt Isn't Handled
|
||||
## Timer Interrupt Isn't Handled
|
||||
|
||||
Previously NuttX hangs midsentence while booting on PinePhone, let's find out how we fixed it...
|
||||
|
||||
|
@ -1582,7 +1584,7 @@ Let's troubleshoot the Timer Interrupt...
|
|||
|
||||
And we're right! The Arm64 Vector Table is indeed incorrectly configured! Here why...
|
||||
|
||||
# Arm64 Vector Table Is Wrong
|
||||
## Arm64 Vector Table Is Wrong
|
||||
|
||||
Earlier we saw that the Interrupt Handler wasn't called for System Timer Interrupt. And it might be due to problems in the __Arm64 Vector Table `_vector_table`__: [arch/arm64/src/common/arm64_vector_table.S](https://github.com/lupyuen/incubator-nuttx/blob/pinephone/arch/arm64/src/common/arm64_vector_table.S#L93-L232)
|
||||
|
||||
|
@ -2067,7 +2069,7 @@ From this we see that NuttX runs mostly in EL1.
|
|||
|
||||
(EL1 is less privileged than EL2, which supports Processor Virtualization)
|
||||
|
||||
# Dump Interrupt Vector Table
|
||||
## Dump Interrupt Vector Table
|
||||
|
||||
This is how we dump the Interrupt Vector Table to troubleshoot Interrupts...
|
||||
|
||||
|
@ -2406,7 +2408,7 @@ This section describes the Boot Sequence for NuttX on PinePhone...
|
|||
|
||||
The next section talks about debugging the Boot Sequence...
|
||||
|
||||
# Boot Debugging
|
||||
## Boot Debugging
|
||||
|
||||
_How can we debug NuttX while it boots?_
|
||||
|
||||
|
@ -2661,7 +2663,7 @@ tcon0_lvds_if_reg=0x80000000
|
|||
nsh>
|
||||
```
|
||||
|
||||
# BASIC Blinks The LEDs
|
||||
## BASIC Blinks The LEDs
|
||||
|
||||
In the previous section we lit up PinePhone's Red, Green and Blue LEDs. Below are the values we wrote to the Allwinner A64 Port Controller...
|
||||
|
||||
|
@ -3165,7 +3167,7 @@ And yet Zig is so similar to C that we can test the Zig Driver with the rest of
|
|||
|
||||
Also `comptime` Compile-Time Expressions in Zig will be helpful when we initialise the ST7703 LCD Controller. [(See this)](https://lupyuen.github.io/articles/dsi#initialise-lcd-controller)
|
||||
|
||||
# Compose MIPI DSI Long Packet in Zig
|
||||
## Compose MIPI DSI Long Packet in Zig
|
||||
|
||||
To initialise PinePhone's ST7703 LCD Controller, our PinePhone Display Driver for NuttX shall send MIPI DSI Long Packets to ST7703...
|
||||
|
||||
|
@ -3175,7 +3177,7 @@ This is how our Zig Driver composes a MIPI DSI Long Packet...
|
|||
|
||||
https://github.com/lupyuen/pinephone-nuttx/blob/1262f46622dc07442cf2aa59a4bbc57871308ed1/display.zig#L140-L204
|
||||
|
||||
# Compose MIPI DSI Short Packet in Zig
|
||||
## Compose MIPI DSI Short Packet in Zig
|
||||
|
||||
For 1 or 2 bytes of data, our PinePhone Display Driver shall send MIPI DSI Short Packets (instead of Long Packets)...
|
||||
|
||||
|
@ -3185,7 +3187,7 @@ This is how our Zig Driver composes a MIPI DSI Short Packet...
|
|||
|
||||
https://github.com/lupyuen/pinephone-nuttx/blob/1262f46622dc07442cf2aa59a4bbc57871308ed1/display.zig#L206-L261
|
||||
|
||||
# Compute Error Correction Code in Zig
|
||||
## Compute Error Correction Code in Zig
|
||||
|
||||
In our PinePhone Display Driver for NuttX, this is how we compute the Error Correction Code for a MIPI DSI Packet...
|
||||
|
||||
|
@ -3193,7 +3195,7 @@ https://github.com/lupyuen/pinephone-nuttx/blob/1262f46622dc07442cf2aa59a4bbc578
|
|||
|
||||
The Error Correction Code is the last byte of the 4-byte Packet Header for Long Packets and Short Packets.
|
||||
|
||||
# Compute Cyclic Redundancy Check in Zig
|
||||
## Compute Cyclic Redundancy Check in Zig
|
||||
|
||||
This is how our PinePhone Display Driver computes the 16-bit Cyclic Redundancy Check (CCITT) in Zig...
|
||||
|
||||
|
@ -3201,7 +3203,7 @@ https://github.com/lupyuen/pinephone-nuttx/blob/1262f46622dc07442cf2aa59a4bbc578
|
|||
|
||||
The Cyclic Redundancy Check is the 2-byte Packet Footer for Long Packets.
|
||||
|
||||
# Test PinePhone MIPI DSI Driver with QEMU
|
||||
## Test PinePhone MIPI DSI Driver with QEMU
|
||||
|
||||
The above Zig Code for composing Long Packets and Short Packets was tested in QEMU for Arm64 with GIC Version 2...
|
||||
|
||||
|
@ -3295,7 +3297,7 @@ Result:
|
|||
00 00 00 00 65 03
|
||||
```
|
||||
|
||||
# Test Case for PinePhone MIPI DSI Driver
|
||||
## Test Case for PinePhone MIPI DSI Driver
|
||||
|
||||
This is how we write a Test Case for the PinePhone MIPI DSI Driver on NuttX...
|
||||
|
||||
|
@ -3318,7 +3320,7 @@ Result:
|
|||
00 00 00 00 65 03
|
||||
```
|
||||
|
||||
# Initialise ST7703 LCD Controller in Zig
|
||||
## Initialise ST7703 LCD Controller in Zig
|
||||
|
||||
PinePhone's ST7703 LCD Controller needs to be initialised with these 20 Commands...
|
||||
|
||||
|
@ -3332,7 +3334,7 @@ To send a command, `writeDcs` executes a DCS Short Write or DCS Long Write, depe
|
|||
|
||||
https://github.com/lupyuen/pinephone-nuttx/blob/40098cd9ea37ab5e0192b2dc006a98630fa6a7e8/display.zig#L431-L453
|
||||
|
||||
# Test Zig Display Driver for PinePhone
|
||||
## Test Zig Display Driver for PinePhone
|
||||
|
||||
To test our Zig Display Driver with NuttX on PinePhone, we'll run this p-boot Display Code...
|
||||
|
||||
|
@ -3518,7 +3520,7 @@ Let's look at the DE Mixers...
|
|||
|
||||
![A64 Display Engine](https://lupyuen.github.io/images/de-block1a.jpg)
|
||||
|
||||
# Display Engine Mixers
|
||||
## Display Engine Mixers
|
||||
|
||||
_What's a Display Engine Mixer?_
|
||||
|
||||
|
@ -3571,7 +3573,7 @@ The 3 UI Overlay Channels would be useful for overlaying a Text UI on top of a V
|
|||
|
||||
[(Wait... Wasn't Pine64 created thanks to OTT Boxes? 🤔)](https://en.wikipedia.org/wiki/Pine64#:~:text=Pine64%20initially%20operated%20as%20Pine%20Microsystems%20Inc.%20(Fremont%2C%20California)%2C%20founded%20by%20TL%20Lim%2C%20the%20inventor%20of%20the%20PopBox%20and%20Popcorn%20Hour%20series%20of%20media%20players%20sold%20under%20the%20Syabas%20and%20Cloud%20Media%20brands.%5B2%5D)
|
||||
|
||||
# Render Colours
|
||||
## Render Colours
|
||||
|
||||
Let's render simple colour blocks on the PinePhone Display.
|
||||
|
||||
|
@ -3646,7 +3648,7 @@ We should see these Blue, Green and Red Blocks...
|
|||
|
||||
Channels 2 and 3 are disabled for now. We'll use them to render UI Overlays later.
|
||||
|
||||
# Render Mandelbrot Set
|
||||
## Render Mandelbrot Set
|
||||
|
||||
Let's render something more interesting... Mandelbrot Set: [test_display.c](https://github.com/lupyuen/incubator-nuttx-apps/blob/de2/examples/hello/test_display.c)
|
||||
|
||||
|
@ -3739,7 +3741,7 @@ Nope, remember that the Display Engine reads our Framebuffer directly via DMA.
|
|||
|
||||
So any updates to the Framebuffer will be pushed to the display instantly.
|
||||
|
||||
# Render Square Overlay
|
||||
## Render Square Overlay
|
||||
|
||||
This is how we render a Blue Square as an Overlay on UI Channel 2: [test_display.c](https://github.com/lupyuen/incubator-nuttx-apps/blob/de2/examples/hello/test_display.c)
|
||||
|
||||
|
@ -3767,7 +3769,7 @@ d->planes[1].dst_x = 52; // Dest X
|
|||
d->planes[1].dst_y = 52; // Dest Y
|
||||
```
|
||||
|
||||
# Render Circle Overlay
|
||||
## Render Circle Overlay
|
||||
|
||||
This is how we render a Green Circle as an Overlay on UI Channel 3: [test_display.c](https://github.com/lupyuen/incubator-nuttx-apps/blob/de2/examples/hello/test_display.c)
|
||||
|
||||
|
@ -3818,7 +3820,7 @@ We should see the Animated Mandelbrot Set, with Blue Square and Green Circle as
|
|||
|
||||
(Why the missing horizontal lines in the Blue Square and Green Circle?)
|
||||
|
||||
# Test PinePhone Display Engine
|
||||
## Test PinePhone Display Engine
|
||||
|
||||
To test the A64 Display Engine with NuttX on PinePhone, we'll run this p-boot Display Code...
|
||||
|
||||
|
@ -3950,7 +3952,7 @@ nuttx
|
|||
|
||||
(The steps look messy today, hopefully we'll remove p-boot after we have created our NuttX Display Driver)
|
||||
|
||||
# Display Engine Usage
|
||||
## Display Engine Usage
|
||||
|
||||
Based on the log captured from our instrumented [test_display.c](https://github.com/lupyuen/incubator-nuttx-apps/blob/de2/examples/hello/test_display.c), we have identified the steps to render 3 UI Channels (1 to 3) with the Display Engine [(`display_commit`)](https://megous.com/git/p-boot/tree/src/display.c#n2017)
|
||||
|
||||
|
@ -4100,7 +4102,7 @@ This is how we'll create a NuttX Driver for PinePhone's A64 Display Engine that
|
|||
|
||||
(See Memory Mapping List and Register List at Page 90)
|
||||
|
||||
# Other Display Engine Features
|
||||
## Other Display Engine Features
|
||||
|
||||
We won't use these Display Engine Features today...
|
||||
|
||||
|
@ -4220,7 +4222,7 @@ https://github.com/lupyuen/pinephone-nuttx/blob/6ba90edb155a0132400ce66752eea761
|
|||
|
||||
![Blue, Green, Red Blocks with Overlays](https://lupyuen.github.io/images/de2-test3.jpg)
|
||||
|
||||
# Test Zig Driver for PinePhone Display Engine
|
||||
## Test Zig Driver for PinePhone Display Engine
|
||||
|
||||
To test the A64 Display Engine with NuttX on PinePhone, we'll run our NuttX Test App...
|
||||
|
||||
|
@ -4548,7 +4550,7 @@ The code looks highly similar!
|
|||
|
||||
![Rendering graphics on PinePhone with Apache NuttX RTOS](https://lupyuen.github.io/images/dsi3-title.jpg)
|
||||
|
||||
# Test MIPI DSI for NuttX Kernel
|
||||
## Test MIPI DSI for NuttX Kernel
|
||||
|
||||
_How do we test the MIPI DSI Driver in the NuttX Kernel?_
|
||||
|
||||
|
@ -4708,7 +4710,7 @@ Note that we capture the [Actual Test Log](test/test.log) and we `diff` it with
|
|||
|
||||
https://github.com/lupyuen/pinephone-nuttx/blob/c04f1447933665df207a42f626c726ef7a7def65/test/test.log#L4-L20
|
||||
|
||||
# Test Timing Controller TCON0 Driver for NuttX Kernel
|
||||
## Test Timing Controller TCON0 Driver for NuttX Kernel
|
||||
|
||||
We're adding the Timing Controller TCON0 Driver to NuttX Kernel...
|
||||
|
||||
|
@ -4756,7 +4758,7 @@ We also tested with Graphics Logging Disabled, to preempt any timing issues...
|
|||
|
||||
- [NuttX Kernel TCON0 Test Log (Graphics Logging Disabled)](https://gist.github.com/lupyuen/61a1374c9ea6a1b7826488da688e8c6c)
|
||||
|
||||
# Test Display Engine Driver for NuttX Kernel
|
||||
## Test Display Engine Driver for NuttX Kernel
|
||||
|
||||
We're adding the Display Engine Driver to NuttX Kernel...
|
||||
|
||||
|
@ -4973,7 +4975,7 @@ There seems to be a lag between the writing of pixels to framebuffer, and the pu
|
|||
|
||||
Here's the fix for this lag...
|
||||
|
||||
# Fix Missing Pixels in PinePhone Image
|
||||
## Fix Missing Pixels in PinePhone Image
|
||||
|
||||
In the previous section we saw that there was a lag pushing pixels from the RAM Framebuffer to the PinePhone Display (over DMA / Display Engine / Timing Controller TCON0).
|
||||
|
||||
|
@ -5298,7 +5300,7 @@ Yep we can read the Touch Coordinates correctly, with polling! (But not so effic
|
|||
|
||||
Let's handle Interrupts from the Touch Panel...
|
||||
|
||||
# Handle Interrupts from Touch Panel
|
||||
## Handle Interrupts from Touch Panel
|
||||
|
||||
In the previous section we've read the Touch Panel by Polling. Which is easier but inefficient.
|
||||
|
||||
|
@ -5479,7 +5481,7 @@ touch_panel_read: touch x=15, y=1394
|
|||
|
||||
Let's move this code into the NuttX Touch Panel Driver for PinePhone...
|
||||
|
||||
# NuttX Touch Panel Driver for PinePhone
|
||||
## NuttX Touch Panel Driver for PinePhone
|
||||
|
||||
We moved the code above into the NuttX Touch Panel Driver for PinePhone...
|
||||
|
||||
|
@ -5606,7 +5608,7 @@ More details here...
|
|||
|
||||
- ["NuttX RTOS for PinePhone: Boot to LVGL"](https://lupyuen.github.io/articles/lvgl2)
|
||||
|
||||
# LVGL Demos on PinePhone
|
||||
## LVGL Demos on PinePhone
|
||||
|
||||
_We've seen the LVGL Widgets Demo on NuttX for PinePhone. What about other demos?_
|
||||
|
||||
|
@ -5701,7 +5703,7 @@ More details here...
|
|||
|
||||
Note that the LVGL Demos start automatically when NuttX boots on PinePhone. Let's talk about this...
|
||||
|
||||
# Boot to LVGL on PinePhone
|
||||
## Boot to LVGL on PinePhone
|
||||
|
||||
_Can we boot NuttX on PinePhone, directly to LVGL? Without a Serial Cable?_
|
||||
|
||||
|
@ -5775,7 +5777,7 @@ We begin by starting the NSH Task and piping a command to NSH Shell...
|
|||
|
||||
![Flow of LVGL Terminal for PinePhone on Apache NuttX RTOS](https://lupyuen.github.io/images/terminal-flow.jpg)
|
||||
|
||||
# Pipe a Command to NuttX NSH Shell
|
||||
## Pipe a Command to NuttX NSH Shell
|
||||
|
||||
Our LVGL Terminal App needs to...
|
||||
|
||||
|
@ -5895,7 +5897,7 @@ There's a problem with the code above... Calling `read()` on `nsh_stdout` will b
|
|||
|
||||
Let's call `poll()` on `nsh_stdout` to check if there's NSH Output to be read...
|
||||
|
||||
# Poll for NSH Output
|
||||
## Poll for NSH Output
|
||||
|
||||
In the previous sections we started an NSH Shell that will execute NSH Commands that we pipe to it.
|
||||
|
||||
|
@ -5987,7 +5989,7 @@ has_input: timeout: fd=8
|
|||
|
||||
This polling needs to be done in an LVGL Timer, here's why...
|
||||
|
||||
# Timer for LVGL Terminal
|
||||
## Timer for LVGL Terminal
|
||||
|
||||
In the previous sections we started an NSH Shell that will execute NSH Commands that we pipe to it.
|
||||
|
||||
|
@ -6055,7 +6057,7 @@ For now, it's simpler to run an LVGL Timer to poll for NSH Output.
|
|||
|
||||
Let's add the polling to the LVGL Timer Callback...
|
||||
|
||||
# Poll for NSH Output in LVGL Timer
|
||||
## Poll for NSH Output in LVGL Timer
|
||||
|
||||
In the previous section we've created an LVGL Timer that's triggered periodically.
|
||||
|
||||
|
@ -6161,7 +6163,7 @@ nsh>
|
|||
|
||||
Now that our background processing is ready, let's render the LVGL Widgets for our terminal...
|
||||
|
||||
# Render Terminal with LVGL Widgets
|
||||
## Render Terminal with LVGL Widgets
|
||||
|
||||
Our LVGL Terminal will have 3 LVGL Widgets...
|
||||
|
||||
|
@ -6230,7 +6232,7 @@ static void create_widgets(void) {
|
|||
|
||||
Note that we're using the LVGL Default Font for all 3 LVGL Widgets. Which has a problem...
|
||||
|
||||
# Set LVGL Terminal Font to Monospace
|
||||
## Set LVGL Terminal Font to Monospace
|
||||
|
||||
Our LVGL Terminal looks nicer with a Monospace Font.
|
||||
|
||||
|
@ -6269,7 +6271,7 @@ Let's look at our Callback Function for the LVGL Keyboard...
|
|||
|
||||
![Set Terminal Font to Monospace](https://lupyuen.github.io/images/lvgl2-terminal3.jpg)
|
||||
|
||||
# Handle Input from LVGL Keyboard
|
||||
## Handle Input from LVGL Keyboard
|
||||
|
||||
Here's the Callback Function that handles input from the LVGL Keyboard.
|
||||
|
||||
|
@ -6323,7 +6325,7 @@ static void input_callback(lv_event_t *e) {
|
|||
|
||||
The command runs in NSH Shell and produces NSH Output. Which is handled by the LVGL Timer Callback Function...
|
||||
|
||||
# Handle Output from NSH Shell
|
||||
## Handle Output from NSH Shell
|
||||
|
||||
Our LVGL Timer Callback Function checks periodically whether there's any NSH Output waiting to be processed.
|
||||
|
||||
|
|
Loading…
Reference in a new issue