f0fb530eaa
Summary: - add support BUILD_KERNEL and SMP for imx6 - prepare page tables of cpu1,2,3 - add sabre-6quad:knsh_smp config Impact: - imx6 Testing: - getprime, smp on sabre-6quad:knsh_smp w/ qemu Signed-off-by: Oki Minabe <minabe.oki@gmail.com>
993 lines
35 KiB
Plaintext
993 lines
35 KiB
Plaintext
README.txt
|
||
==========
|
||
|
||
This directory holds a port of NuttX to the NXP/Freescale Sabre board
|
||
featuring the iMX 6Quad CPU.
|
||
|
||
This is a minimal port, used primarily for verifying SMP operation. More
|
||
recently, a port to the i.MX RT was added. This port has gotten more
|
||
support since it is better aligned with usage in embedded systems. The
|
||
i.MX6 and the i.MX6 share IOMUXing and some peripherals. It ought to be
|
||
a simple matter to backport some of the common drivers from i.MXRT to i.MX6.
|
||
|
||
Contents
|
||
========
|
||
|
||
- Status
|
||
- Platform Features
|
||
- Serial Console
|
||
- LEDs and Buttons
|
||
- Using U-Boot to Run NuttX
|
||
- Debugging with the Segger J-Link
|
||
- SMP
|
||
- Configurations
|
||
|
||
Status
|
||
======
|
||
|
||
2016-02-28: The i.MX6Q port is just beginning. A few files have been
|
||
populated with the port is a long way from being complete or even ready to
|
||
begin any kind of testing.
|
||
|
||
2016-03-12: The i.MX6Q port is code complete including initial
|
||
implementation of logic needed for CONFIG_SMP=y . There is no clock
|
||
configuration logic. This is probably not an issue if we are loaded into
|
||
SDRAM by a bootloader (because we cannot change the clocking anyway in
|
||
that case).
|
||
|
||
There is a lot of testing that could be done but, unfortunately, I still
|
||
have no i.MX6 hardware to test on.
|
||
|
||
In additional to the unexpected issues, I do expect to run into some
|
||
cache coherency issues when I get to testing an SMP configuration.
|
||
|
||
2016-03-28: I now have a used MCIMX6Q-SDB which is similar to the target
|
||
configuration described below except that it does not have the 10.1" LVDS
|
||
display. Next step: Figure out how to run a copy of NuttX using U-Boot.
|
||
|
||
2016-03-31: Most all of the boot of the NSH configuration seems to be
|
||
working. It gets to NSH and NSH appears to run normally. Non-interrupt
|
||
driver serial output to the VCOM console is working (llsyslog). However,
|
||
there does not appear to be any interrupt activity: No timer interrupts,
|
||
no interrupt driver serial console output (syslog, printf).
|
||
|
||
2016-05-16: I now get serial interrupts (but not timer interrupts). This
|
||
involves a few changes to GIC bit settings that I do not fully understand.
|
||
With this change, the NSH serial console works:
|
||
|
||
MX6Q SABRESD U-Boot > ABEFGHILMN
|
||
|
||
NuttShell (NSH)
|
||
nsh>
|
||
|
||
But there are still no timer interrupts. LEDs do not appear to be working.
|
||
|
||
2016-05-17: Timer interrupts now work. This turned out to be just a minor
|
||
bit setting error in the timer configuration. LEDs were not working simply
|
||
because board_autoled_initialize() was not being called in the board startup
|
||
logic.
|
||
|
||
At this point, I would say that the basic NSH port is complete.
|
||
|
||
2016-05-18: Started looking at the SMP configuration. Initially, I verfied
|
||
that the NSH configuration works with CONFIG_SMP_NCPUS=1. Not a very
|
||
interesting case, but this does exercise a lot of the basic SMP logic.
|
||
|
||
When more than one CPU is configured, then there are certain failures that
|
||
appear to be stack corruption problem. See the open issues below under
|
||
SMP.
|
||
|
||
2016-05-22: In a simple NSH case, SMP does not seem to be working. But there
|
||
are known SMP open issues so I assume if the tasking were stressed more there
|
||
would be additional failures. See the open issues below under SMP.
|
||
|
||
An smp configuration was added. This is not quite the same as the
|
||
configuration that I used for testing. I enabled DEBUG output, ran with
|
||
only 2 CPUS, and disabled the RAMLOG:
|
||
|
||
+CONFIG_DEBUG_FEATURES=y
|
||
+CONFIG_DEBUG_INFO=y
|
||
+CONFIG_DEBUG_SCHED=y
|
||
+CONFIG_DEBUG_SYMBOLS=y
|
||
|
||
-CONFIG_DEBUG_FULLOPT=y
|
||
+CONFIG_DEBUG_NOOPT=y
|
||
|
||
-CONFIG_SMP_NCPUS=4
|
||
+CONFIG_SMP_NCPUS=2
|
||
|
||
-CONFIG_RAMLOG=y
|
||
-CONFIG_RAMLOG_SYSLOG=y
|
||
-CONFIG_RAMLOG_BUFSIZE=16384
|
||
-CONFIG_RAMLOG_NONBLOCKING=y
|
||
-CONFIG_RAMLOG_NPOLLWAITERS=4
|
||
|
||
I would also disable debug output from CPU0 so that I could better see the
|
||
debug output from CPU1. In drivers/syslog/vsyslog.c:
|
||
|
||
+if (up_cpu_index() == 0) return 17; // REMOVE ME
|
||
|
||
2016-11-26: With regard to SMP, the major issue is cache coherency. I added
|
||
some special build logic to move spinlock data into the separate, non-
|
||
cached section. That gives an improvement in performance but there are
|
||
still hangs. These, I have determined, are to other kinds of cache
|
||
coherency problems. Semaphores, message queues, etc. basically all
|
||
shared data must be made coherent.
|
||
|
||
I also added some SCU controls that should enable cache consistency for SMP
|
||
CPUs, but I don't think I have that working right yet. See the SMP section
|
||
below for more information.
|
||
|
||
2016-11-28: SMP is unusable until the SCU cache coherency logic is fixed.
|
||
I do not know how to do that now.
|
||
|
||
2016-12-01: I committed a completely untested SPI driver. This was taken
|
||
directly from the i.MX1 and is most certainly not ready for use yet.
|
||
|
||
2016-12-07: Just a note to remind myself. The PL310 L2 cache has *not*
|
||
yet been enabled.
|
||
|
||
2018-02-06: Revisited SMP to see how much has been broken due to bit rot.
|
||
Several fixes were needed mostly due to: (1) The new version of
|
||
this_task() that calls sched_lock() and sched_unlock(), and (2) to
|
||
deferred setting g_cpu_irqlock(). That latter setting is now deferred
|
||
until nxsched_resume_scheduler() runs. These commits were made:
|
||
|
||
commit 50ab5d638a37b539775d1e60085f182bf26be57f
|
||
sched/task: It is not appropriate for logic in nxtask_exit() to call
|
||
the new version of this_task(). sched/irq: Remove redundant fetch
|
||
of CPU index; boards/sabre-6quad: update README.
|
||
|
||
commit 0ba78530164814360eb09ed9805137b934c6f03b
|
||
sched/irq: Fix a infinite recursion problem that a recent change
|
||
introduced into the i.MX6 SMP implementation.
|
||
|
||
commit 8aa15385060bf705bbca2c22a5682128740e55a8
|
||
arch/arm/src/armv7-a: Found some additional places were the new
|
||
this_task() function cannot be called in the i.MX6 SMP configuration.
|
||
|
||
commit de34b4523fc33c6f2f20619349af8fa081a3bfcd
|
||
sched/ and arch/arm/src/armv7-a: Replace a few more occurrences
|
||
of this_task() with current_task(cpu) in an effort to get the i.MX6
|
||
working in SMP mode again. It does not yet work, sadly.
|
||
|
||
commit cce21bef3292a40dcd97b6176ea016e2b559de8b
|
||
sched/sched: sched_lock() and sched_unlock().. back out some changes
|
||
I made recently. The seemed correct but apparently not. Also
|
||
reorder to logic so that g_global_lockcount is incremented for the very
|
||
minimum amount of time.
|
||
|
||
With these changes, basic SMP functionality is restored and there are no
|
||
known issues (Configuration 'smp' with 4 CPUs and data cache disabled).
|
||
It is possible, however, that additional changes similar to the above will
|
||
be required in other areas of the OS, but none such are known as of this
|
||
writing. Insufficient stress testing has been done to prove that the
|
||
solution is stable.
|
||
|
||
2018-06-08: Again revisited SMP. There appears to be a memory corruption problem.
|
||
This is rarely seen with the SMP test but you enable the OS test in the smp
|
||
configuration, you will see a crash due to memory corruption consistently,
|
||
specially in the nested signal test (apps/examples/ostest/signest.c).
|
||
|
||
2018-06-20: There was a problem with the Interrupt Stack for SMP in
|
||
arch/arm/src/armv7-a/arm_vectors.S: There is only one interrupt stack for
|
||
all CPUs! A fix for this was put in place on 2018-06-21. Big Improvement!
|
||
But this does not completely eliminate instabilities which seem to be
|
||
related to memory corruption -- mm_mallinfo() asserts.
|
||
|
||
Platform Features
|
||
=================
|
||
|
||
Processor:
|
||
- i.MX 6Quad or 6DualLite 1 GHz ARM Cortex-A9 processor
|
||
Memory/storage:
|
||
- 1 GB DDR3 SDRAM up to 533 MHz (1066 MTPS) memory
|
||
- 8 GB eMMC flash
|
||
- 4 MB SPI NOR flash
|
||
Display:
|
||
- 10.1" 1024 x 768 LVDS display with integrated P-cap sensing
|
||
- HDMI connector
|
||
- LVDS connector (for optional second display)
|
||
- LCD expansion connector (parallel, 24-bit)
|
||
- EPDC expansion connector (for 6DualLite only)
|
||
- MIPI DSI connector (two data lanes, 1 GHz each)
|
||
User Interface:
|
||
- 10.1" capacitive multitouch display
|
||
- Buttons: power, reset, volume
|
||
Power Management:
|
||
- Proprietary PF0100 PMIC
|
||
Audio:
|
||
- Audio codec
|
||
- 2x digital microphones
|
||
- 2x 3.5 mm audio ports
|
||
- Dual 1 watt speakers
|
||
Expansion Connector:
|
||
- Camera MIPI CSI port
|
||
- I2C, SPI signals
|
||
Connectivity:
|
||
- 2x full-size SD/MMC card slots
|
||
- 7-pin SATA data connector
|
||
- 10/100/1000 Ethernet port
|
||
- 1x USB 2.0 OTG port (micro USB)
|
||
Debug:
|
||
- JTAG connector (20-pin)
|
||
- 1x Serial-to-USB connector (for JTAG)
|
||
OS Support:
|
||
- Linux<75> and Android<69> from NXP/Freescale
|
||
- Others supported via third party (QNX, Windows Embedded)
|
||
Tools Support:
|
||
- Manufacturing tool from NXP/Freescale
|
||
- IOMUX tool from NXP/Freescale
|
||
- Lauterbach, ARM (DS-5), IAR and Macraigor
|
||
Additional Features:
|
||
- Proprietary 3-axis accelerometer
|
||
- Proprietary 3D magnetometer
|
||
- Ambient light sensor
|
||
- GPS receiver module
|
||
- 2x 5MP cameras
|
||
- Battery charger
|
||
- Battery connectors (battery not included)
|
||
|
||
Serial Console
|
||
==============
|
||
|
||
A DEBUG VCOM is available MICRO USB AB 5 J509. This corresponds to UART1
|
||
from the i.MX6. UART1 connects to J509 via the CSIO_DAT10 and CSIO_DAT11
|
||
pins
|
||
|
||
LEDs and Buttons
|
||
================
|
||
|
||
LEDs
|
||
----
|
||
A single LED is available driven GPIO1_IO02. On the schematic this is
|
||
USR_DEF_RED_LED signal to pin T1 (GPIO_2). This signal is shared with
|
||
KEY_ROW6 (ALT2). A high value illuminates the LED.
|
||
|
||
This LED is not used by the board port unless CONFIG_ARCH_LEDS is
|
||
defined. In that case, the usage by the board port is defined in
|
||
include/board.h and src/sam_autoleds.c. The LED is used to encode
|
||
OS-related events as follows:
|
||
|
||
------------------- ----------------------- ------
|
||
SYMBOL Meaning LED
|
||
------------------- ----------------------- ------
|
||
LED_STARTED NuttX has been started OFF
|
||
LED_HEAPALLOCATE Heap has been allocated OFF
|
||
LED_IRQSENABLED Interrupts enabled OFF
|
||
LED_STACKCREATED Idle stack created ON
|
||
LED_INIRQ In an interrupt N/C
|
||
LED_SIGNAL In a signal handler N/C
|
||
LED_ASSERTION An assertion failed N/C
|
||
LED_PANIC The system has crashed FLASH
|
||
|
||
Thus if the LED is statically on, NuttX has successfully booted and is,
|
||
apparently, running normally. If the LED is flashing at approximately
|
||
2Hz, then a fatal error has been detected and the system has halted.
|
||
|
||
Buttons
|
||
-------
|
||
|
||
Using U-Boot to Run NuttX
|
||
=========================
|
||
|
||
The MCIMX6Q-SDB comes with a 8GB SD card containing the U-Boot and Android.
|
||
You simply put the SD card in the SD card slot SD3 (on the bottom of the
|
||
board next to the HDMI connect) and Android 4.2.2.1 will boot.
|
||
|
||
But we need some other way to boot NuttX. Here are some things that I have
|
||
experimented with.
|
||
|
||
Building U-Boot (Failed Attempt #1)
|
||
-----------------------------------
|
||
|
||
I have been unsuccessful getting building a working version of u-boot from
|
||
scratch. It builds, but it does not run. Here are the things I did:
|
||
|
||
1. Get a copy of the u-boot i.MX6 code and Android GCC toolchain
|
||
|
||
$ git clone https://source.codeaurora.org/external/imx/uboot-imx.git -b nxp/imx_v2009.08
|
||
$ git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6
|
||
|
||
2. Build U-Boot for the i.MX6Q Sabre using the following steps. This
|
||
assumes that you have the path to the above toolchain at the
|
||
beginning of your PATH variable:
|
||
|
||
$ cd uboot-imx
|
||
$ export ARCH=arm
|
||
$ export CROSS_COMPILE=arm-eabi-
|
||
$ make mx6q_sabresd_android_config
|
||
$ make
|
||
|
||
This should create a number of files, including u-boot.bin
|
||
|
||
3. Format an SD card
|
||
|
||
Create a FAT16 partition at an offset of about 1MB into the SD card.
|
||
This is where we will put nuttx.bin.
|
||
|
||
4. Put U-Boot on SD.
|
||
|
||
$ dd if=u-boot.bin of=/dev/<your-sd-card> bs=1k
|
||
$ sync
|
||
|
||
Your SD card device is typically something in /dev/sd<X> or
|
||
/dev/mmcblk<X>. Note that you need write permissions on the SD card
|
||
for the command to succeed, so you might need to su - as root, or use
|
||
sudo, or do a chmod a+w as root on the SD card device node to grant
|
||
permissions to users.
|
||
|
||
Using the Other SD Card Slot (Failed Attempt #2)
|
||
------------------------------------------------
|
||
|
||
Another option is to use the version u-boot that came on the 8GB but put
|
||
NuttX on another SD card inserted in the other SD card slot at the opposite
|
||
corner of the board.
|
||
|
||
To make a long story short: This doesn't work. As far as I can tell,
|
||
U-Boot does not support any other other SC card except for mmc 2 with is the
|
||
boot SD card slot.
|
||
|
||
Replace Boot SD Card (Successful Attempt #3)
|
||
--------------------------------------------
|
||
|
||
What if you remove the SD card after U-boot has booted, then then insert
|
||
another SD card containing the nuttx.bin image?
|
||
|
||
1. Build nuttx.bin and copy it only a FAT formatted SD card. Insert the SD
|
||
card containing NuttX into the "other" SD card slot. Insert the 8GB SD
|
||
card with U-boot already on it in the normal, boot SD card slot.
|
||
|
||
2. Connect the VCOM port using the USB port next to the boot SD card slot.
|
||
|
||
3. Start a console at 11500 8N1 on the VCOM port
|
||
|
||
4. Power up the board with the 8GB SD card in place. U-Boot will start and
|
||
countdown before starting Linux. Press enter to break into U-Boot before
|
||
Linux is started.
|
||
|
||
5. Remove the 8GB U-Boot SD card; insert in its place.
|
||
|
||
6. Rescan the SD card:
|
||
|
||
MX6Q SABRESD U-Boot > mmc dev 2
|
||
mmc2 is current device
|
||
MX6Q SABRESD U-Boot > mmc rescan
|
||
MX6Q SABRESD U-Boot > fatls mmc 2
|
||
system volume information/
|
||
87260 nuttx.bin
|
||
|
||
1 file(s), 1 dir(s)
|
||
|
||
7. Then we can boot NuttX off the rescanned SD card:
|
||
|
||
MX6Q SABRESD U-Boot > fatload mmc 2 0x10800000 nuttx.bin
|
||
reading nuttx.bin
|
||
|
||
87260 bytes read
|
||
MX6Q SABRESD U-Boot > go 0x10800040
|
||
## Starting application at 0x10800040 ...
|
||
|
||
That seems to work okay.
|
||
|
||
Use the FAT Partition on the 8GB SD Card (Untested Idea #4)
|
||
-----------------------------------------------------------
|
||
|
||
Partition 4 on the SD card is an Android FAT file system. So one thing you
|
||
could do would be put the nuttx.bin file on that partition, then boot like:
|
||
|
||
MX6Q SABRESD U-Boot > fatload mmc 2:4 0x10800000 nuttx.bin
|
||
|
||
SD Card Image Copy (Successful Attempt #5)
|
||
------------------------------------------
|
||
|
||
You can use the 'dd' command to copy the first couple of megabytes from the
|
||
8GB SD card and copy that to another SD card. You then have to use 'fdisk'
|
||
to fix the partition table and to add a single FAT16 partition at an offset
|
||
of 1MB or so.
|
||
|
||
1. Insert the 8GB boot SD card into your PC: Copy the first 2Mb from the SD
|
||
card to a file:
|
||
|
||
$ dd if=/dev/sdh of=sdh.img bs=512 count=4096
|
||
|
||
2. Remove the 8GB boot SD card and replace it with a fresh SD card. Copy the
|
||
saved file to the first the new SD card:
|
||
|
||
$ dd of=/dev/sdh if=sdh.img bs=512 count=4096
|
||
|
||
3. Then use 'fdisk' to:
|
||
|
||
- Remove all of the non-existent partitions created by the 'dd' copy.
|
||
- Make a single FAT16 partition at the end of the SD card.
|
||
|
||
You will also need to format the partion for FAT.
|
||
|
||
4. You can put nuttx.bin here and then boot very simply with:
|
||
|
||
MX6Q SABRESD U-Boot > fatload mmc 2:1 0x10800000 nuttx.bin
|
||
MX6Q SABRESD U-Boot > go 0x10800040
|
||
|
||
A little hokey, but not such a bad solution.
|
||
|
||
TFTPBOOT (Successful Attempt #6)
|
||
------------------------------------------
|
||
|
||
If you can prepare tftp server, this approach would be easy
|
||
|
||
1. Copy nuttx.bin to the tftp server (e.g. /var/lib/tftpboot/ )
|
||
|
||
2. Load nuttx.bin from the server and boot
|
||
|
||
MX6Q SABRESD U-Boot > setenv ipaddr 192.168.10.103
|
||
MX6Q SABRESD U-Boot > setenv serverip 192.168.10.16
|
||
MX6Q SABRESD U-Boot > setenv image nuttx.bin
|
||
MX6Q SABRESD U-Boot > tftp ${loadaddr} ${image}
|
||
PHY indentify @ 0x1 = 0x004dd074
|
||
FEC: Link is Up 796d
|
||
Using FEC0 device
|
||
TFTP from server 192.168.10.16; our IP address is 192.168.10.103
|
||
Filename 'nuttx.bin'.
|
||
Load address: 0x10800000
|
||
Loading: ###############
|
||
done
|
||
Bytes transferred = 217856 (35300 hex)
|
||
MX6Q SABRESD U-Boot > go ${loadaddr}
|
||
## Starting application at 0x10800000 ...
|
||
|
||
NuttShell (NSH) NuttX-10.0.1
|
||
nsh>
|
||
|
||
Debugging with the Segger J-Link
|
||
================================
|
||
|
||
These procedures work for debugging the boot-up sequence when there is a
|
||
single CPU running and not much else going on. If you want to do higher
|
||
level debugger, you will need something more capable. NXP/Freescale suggest
|
||
some other debuggers that you might want to consider.
|
||
|
||
These instructions all assume that you have built NuttX with debug symbols
|
||
enabled. When debugging the nuttx.bin file on the SD card, it is also
|
||
assumed the nuttx ELF file with the debug symbol addresses is from the
|
||
same build so that the symbols match up.
|
||
|
||
Debugging the NuttX image on the SD card
|
||
----------------------------------------
|
||
|
||
1. Connect the J-Link to the 20-pin JTAG connector.
|
||
|
||
2. Connect the "USB TO UART" USB VCOM port to the host PC. Start a
|
||
terminal emulation program like TeraTerm on Minicom. Select the USB
|
||
VCOM serial port at 115200 8N1.
|
||
|
||
When you apply power to the board, you should see the U-Boot messages in
|
||
the terminal window. Stop the U-Boot countdown to get to the U-Boot
|
||
prompt.
|
||
|
||
3. Start the Segger GDB server:
|
||
|
||
Target: MCIMX6Q6
|
||
Target Interface: JTAG
|
||
|
||
If the GDB server starts correctly you should see the following in the
|
||
Log output:
|
||
|
||
Waiting for GDB Connection
|
||
|
||
4. In another Xterm terminal window, start arm-none-eabi-gdb and connect to
|
||
the GDB server.
|
||
|
||
From the Xterm Window:
|
||
$ arm-none-eabi-gdb
|
||
|
||
You will need to have the path to the arm-none-eabi-gdb program in your
|
||
PATH variable.
|
||
|
||
Then from GDB:
|
||
gdb> target connect localhost:2331
|
||
gdb> mon halt
|
||
|
||
5. Start U-boot under GDB control:
|
||
|
||
From GDB:
|
||
gdb> mon reset
|
||
gdb> mon go
|
||
|
||
Again stop the U-Boot countdown to get to the U-Boot prompt.
|
||
|
||
6. Load NuttX from the SD card into RAM
|
||
|
||
From U-Boot:
|
||
MX6Q SABRESD U-Boot > fatload mmc 2:1 0x10800000 nuttx.bin
|
||
|
||
7. Load symbols and set a breakpoint
|
||
|
||
From GDB:
|
||
gdb> mon halt
|
||
gdb> file nuttx
|
||
gdb> b __start
|
||
gdb> c
|
||
|
||
__start is the entry point into the NuttX binary at 0x10800040. You can,
|
||
of course, use a different symbol if you want to start debugging later
|
||
in the boot sequence.
|
||
|
||
8. Start NuttX
|
||
|
||
From U-Boot:
|
||
MX6Q SABRESD U-Boot > go 0x10800040
|
||
|
||
9. You should hit the breakpoint that you set above and be off and
|
||
debugging.
|
||
|
||
Debugging a Different NuttX Image
|
||
---------------------------------
|
||
|
||
Q: What if I want do run a different version of nuttx than the nuttx.bin
|
||
file on the SD card. I just want to build and debug without futzing with
|
||
the SD card. Can I do that?
|
||
|
||
A: Yes with the following modifications to the procedure above.
|
||
|
||
- Follow steps 1-5, i.e.,
|
||
|
||
1. Connect the J-Link to the 20-pin JTAG connector.
|
||
2. Connect the "USB TO UART" USB VCOM port to the host PC and start a
|
||
terminal emulation program.
|
||
3. Start the Segger GDB server.
|
||
4. Start arm-none-eabi-gdb and connect to the GDB server.
|
||
5. Start U-boot under GDB control, stopping the countdown to get
|
||
the U-boot prompt.
|
||
|
||
- Skip step 6, don't bother to load NuttX into RAM
|
||
- In step 7, load NuttX into RAM like this:
|
||
|
||
gdb> mon halt
|
||
gdb> load nuttx <-- Loads NuttX into RAM at 0x010800000
|
||
gdb> file nuttx
|
||
gdb> b __start
|
||
gdb> c
|
||
|
||
- Then after step 7, you should hit the breakpoint at the instruction you
|
||
just loaded at address 0x10800040.
|
||
|
||
- Or, in step 6, instead of continuing ('c') which will resume U-Boot,
|
||
even just:
|
||
|
||
gdb> mon halt
|
||
gdb> load nuttx <-- Loads NuttX into RAM at 0x010800000
|
||
gdb> file nuttx
|
||
gdb> mon reg pc 0x10800040
|
||
gdb> s
|
||
|
||
The final single will then step into the freshly loaded program.
|
||
You can then forget about steps 8 and 9.
|
||
|
||
This is, in fact, my preferred way to debug.
|
||
|
||
NOTE: Setting the PC to 0x10800040 is a superstituous step. The PC
|
||
will be set 0x10800040 by the 'load nuttx' command.
|
||
|
||
You can restart the debug session at any time at the gdb> prompt by:
|
||
|
||
gdb> mon reset
|
||
gdb> mon go
|
||
|
||
That will restart U-Boot and you have to press ENTER in the terminal
|
||
window to stop U-Boot. Restarting U-Boot is a necessary part of the
|
||
restart process because you need to put the hardware back in its initial
|
||
state before running NuttX.
|
||
|
||
Then this will restart the debug session just as before:
|
||
|
||
gdb> mon halt
|
||
gdb> load nuttx <-- Loads NuttX into RAM at 0x010800000
|
||
gdb> file nuttx
|
||
gdb> mon reg pc 0x10800040
|
||
gdb> s
|
||
|
||
Debugging with QEMU
|
||
================================
|
||
|
||
The nuttx ELF image can be debugged with QEMU.
|
||
|
||
1. To debug the nuttx (ELF) with symbols, following change must
|
||
be applied to defconfig.
|
||
|
||
diff --git a/boards/arm/imx6/sabre-6quad/configs/nsh/defconfig b/boards/arm/imx6/sabre-6quad/configs/nsh/defconfig
|
||
index b15becbb51..3ad4d13ad7 100644
|
||
--- a/boards/arm/imx6/sabre-6quad/configs/nsh/defconfig
|
||
+++ b/boards/arm/imx6/sabre-6quad/configs/nsh/defconfig
|
||
@@ -21,11 +21,12 @@ CONFIG_ARCH_STACKDUMP=y
|
||
CONFIG_BOARD_LOOPSPERMSEC=99369
|
||
CONFIG_BOOT_RUNFROMSDRAM=y
|
||
CONFIG_BUILTIN=y
|
||
+CONFIG_DEBUG_FULLOPT=y
|
||
+CONFIG_DEBUG_SYMBOLS=y
|
||
CONFIG_DEV_ZERO=y
|
||
|
||
2. Please note that QEMU does not report PL310 (L2CC) related
|
||
registers correctly, so if you enable CONFIG_DEBUG_ASSERTION
|
||
the nuttx will stop with DEBUGASSERT(). To avoid this,
|
||
comment out the following lines.
|
||
|
||
--- a/arch/arm/src/armv7-a/arm_l2cc_pl310.c
|
||
+++ b/arch/arm/src/armv7-a/arm_l2cc_pl310.c
|
||
@@ -333,7 +333,7 @@ void arm_l2ccinitialize(void)
|
||
#if defined(CONFIG_ARMV7A_ASSOCIATIVITY_8WAY)
|
||
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_ASS) == 0);
|
||
#elif defined(CONFIG_ARMV7A_ASSOCIATIVITY_16WAY)
|
||
- DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_ASS) == L2CC_ACR_ASS);
|
||
+ //DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_ASS) == L2CC_ACR_ASS);
|
||
#else
|
||
# error No associativity selected
|
||
#endif
|
||
@@ -345,8 +345,8 @@ void arm_l2ccinitialize(void)
|
||
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
|
||
L2CC_ACR_WAYSIZE_32KB);
|
||
#elif defined(CONFIG_ARMV7A_WAYSIZE_64KB)
|
||
- DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
|
||
- L2CC_ACR_WAYSIZE_64KB);
|
||
+ // DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
|
||
+ // L2CC_ACR_WAYSIZE_64KB);
|
||
#elif defined(CONFIG_ARMV7A_WAYSIZE_128KB)
|
||
DEBUGASSERT((getreg32(L2CC_ACR) & L2CC_ACR_WAYSIZE_MASK) ==
|
||
L2CC_ACR_WAYSIZE_128KB);
|
||
|
||
3. Run QEMU
|
||
|
||
Run qemu with following options, these options do not load nuttx.
|
||
Instead, just stops the emulated CPU like "reset halt" with OpenOCD.
|
||
|
||
$ qemu-system-arm -M sabrelite -smp 4 -nographic -s -S
|
||
|
||
NOTE: -smp 4 option should be used for both nsh configuration
|
||
(non-SMP) and smp configuration (regardless of CONFIG_SMP_NCPUS)
|
||
|
||
To quit QEMU, type Ctrl-A + X
|
||
|
||
3. Run gdb, connect to QEMU, load nuttx and continue
|
||
|
||
$ arm-none-eabi-gdb ./nuttx
|
||
(gdb) target extended-remote :1234
|
||
Remote debugging using :1234
|
||
0x00000000 in ?? ()
|
||
(gdb) load nuttx
|
||
Loading section .text, size 0x17f6b lma 0x10800000
|
||
Loading section .ARM.exidx, size 0x8 lma 0x10817f6c
|
||
Loading section .data, size 0x98 lma 0x10817f74
|
||
Start address 0x10800040, load size 98315
|
||
Transfer rate: 8728 KB/sec, 1927 bytes/write.
|
||
(gdb) c
|
||
Continuing.
|
||
^C
|
||
Thread 1 received signal SIGINT, Interrupt.
|
||
up_idle () at common/up_idle.c:78
|
||
78 }
|
||
(gdb) where
|
||
#0 up_idle () at common/up_idle.c:78
|
||
#1 0x10801ba4 in nx_start () at init/nx_start.c:874
|
||
#2 0x00000000 in ?? ()
|
||
(gdb) info threads
|
||
Id Target Id Frame
|
||
* 1 Thread 1 (CPU#0 [halted ]) up_idle () at common/up_idle.c:78
|
||
2 Thread 2 (CPU#1 [halted ]) 0x00000000 in ?? ()
|
||
3 Thread 3 (CPU#2 [halted ]) 0x00000000 in ?? ()
|
||
4 Thread 4 (CPU#3 [halted ]) 0x00000000 in ?? ()
|
||
|
||
SMP
|
||
===
|
||
|
||
The i.MX6 6Quad has 4 CPUs. Support is included for testing an SMP
|
||
configuration. That configuration is still not yet ready for usage but can
|
||
be enabled with the following configuration settings:
|
||
|
||
RTOS Features -> Tasks and Scheduling
|
||
CONFIG_SPINLOCK=y
|
||
CONFIG_SMP=y
|
||
CONFIG_SMP_NCPUS=4
|
||
|
||
Open Issues:
|
||
|
||
1. Currently all device interrupts are handled on CPU0 only. Critical sections will
|
||
attempt to disable interrupts but will now disable interrupts only on the current
|
||
CPU (which may not be CPU0). There is a spinlock to prohibit entrance into these
|
||
critical sections in interrupt handlers of other CPUs.
|
||
|
||
When the critical section is used to lock a resource that is also used by
|
||
interrupt handling, the interrupt handling logic must also take the spinlock.
|
||
This will cause the interrupt handlers on other CPUs to spin until
|
||
leave_critical_section() is called. More verification is needed.
|
||
|
||
2. Recent redesigns to SMP of another ARMv7-M platform have made changes to the OS
|
||
SMP support. There are no known problem but the changes have not been verified
|
||
fully (see STATUS above for 2019-02-06).
|
||
|
||
Configurations
|
||
==============
|
||
|
||
Information Common to All Configurations
|
||
----------------------------------------
|
||
Each Sabre-6Quad configuration is maintained in a sub-directory and
|
||
can be selected as follow:
|
||
|
||
tools/configure.sh sabre-6quad:<subdir>
|
||
|
||
Before building, make sure the PATH environment variable includes the
|
||
correct path to the directory than holds your toolchain binaries.
|
||
|
||
And then build NuttX by simply typing the following. At the conclusion of
|
||
the make, the nuttx binary will reside in an ELF file called, simply, nuttx.
|
||
|
||
make oldconfig
|
||
make
|
||
|
||
The <subdir> that is provided above as an argument to the tools/configure.sh
|
||
must be is one of the following.
|
||
|
||
NOTES:
|
||
|
||
1. These configurations use the mconf-based configuration tool. To
|
||
change any of these configurations using that tool, you should:
|
||
|
||
a. Build and install the kconfig-mconf tool. See nuttx/README.txt
|
||
see additional README.txt files in the NuttX tools repository.
|
||
|
||
b. Execute 'make menuconfig' in nuttx/ in order to start the
|
||
reconfiguration process.
|
||
|
||
2. Unless stated otherwise, all configurations generate console
|
||
output on UART1 which is a available to the host PC from the USB
|
||
micro AB as a VCOM part.
|
||
|
||
3. All of these configurations are set up to build under Windows using the
|
||
"GNU Tools for ARM Embedded Processors" that is maintained by ARM
|
||
(unless stated otherwise in the description of the configuration).
|
||
|
||
https://developer.arm.com/open-source/gnu-toolchain/gnu-rm
|
||
|
||
That toolchain selection can easily be reconfigured using
|
||
'make menuconfig'. Here are the relevant current settings:
|
||
|
||
Build Setup:
|
||
CONFIG_HOST_WINDOWS=y : Window environment
|
||
CONFIG_WINDOWS_CYGWIN=y : Cywin under Windows
|
||
|
||
System Type -> Toolchain:
|
||
CONFIG_ARMV7M_TOOLCHAIN_GNU_EABI=y : GNU ARM EABI toolchain
|
||
|
||
Configuration sub-directories
|
||
-----------------------------
|
||
|
||
nsh
|
||
---
|
||
This is a NuttShell (NSH) configuration that uses the NSH library
|
||
at apps/nshlib with the start logic at apps/examples/nsh.
|
||
|
||
NOTES:
|
||
|
||
1. This configuration assumes that we are loaded into SDRAM and
|
||
started via U-Boot.
|
||
|
||
2. The serial console is configured by default for use UART1, the
|
||
USB VCOM port (UART1), same as the serial port used by U-Boot.
|
||
You will need to reconfigure if you want to use a different UART.
|
||
|
||
3. NSH built-in applications are supported, but no built-in
|
||
applications are enabled.
|
||
|
||
Binary Formats:
|
||
CONFIG_BUILTIN=y : Enable support for built-in programs
|
||
|
||
Application Configuration:
|
||
CONFIG_NSH_BUILTIN_APPS=y : Enable starting apps from NSH command line
|
||
|
||
4. The RAMLOG is enabled. All SYSLOG (DEBUG) output will go to the
|
||
RAMLOG and will not be visible unless you use the nsh 'dmesg'
|
||
command. To disable this RAMLOG feature, disable the following:
|
||
|
||
Device Drivers: CONFIG_RAMLOG
|
||
|
||
smp
|
||
---
|
||
This is a configuration of testing the SMP configuration. It is
|
||
essentially equivalent to the nsh configuration except has SMP enabled
|
||
and supports apps/testing/smp.
|
||
|
||
Sample output of the SMP test is show below (Configuration all 4 CPUs
|
||
but with data cache disabled):
|
||
|
||
NuttShell (NSH) NuttX-7.23
|
||
nsh> smp
|
||
Main[0]: Running on CPU0
|
||
Main[0]: Initializing barrier
|
||
Thread[1]: Started
|
||
Main[0]: Thread 1 created
|
||
Thread[1]: Running on CPU0
|
||
Main[0]: Now running on CPU1
|
||
Thread[2]: Started
|
||
Main[0]: Thread 2 created
|
||
Thread[2]: Running on CPU1
|
||
Main[0]: Now running on CPU2
|
||
Thread[3]: Started
|
||
Main[0]: Thread 3 created
|
||
Thread[3]: Running on CPU2
|
||
Main[0]: Now running on CPU3
|
||
Thread[4]: Started
|
||
Thread[4]: Running on CPU3
|
||
Main[0]: Thread 4 created
|
||
Main[0]: Now running on CPU0
|
||
Thread[5]: Started
|
||
Thread[5]: Running on CPU0
|
||
Main[0]: Thread 5 created
|
||
Thread[6]: Started
|
||
Thread[6]: Running on CPU0
|
||
Main[0]: Thread 6 created
|
||
Thread[7]: Started
|
||
Thread[7]: Running on CPU0
|
||
Main[0]: Thread 7 created
|
||
Thread[8]: Started
|
||
Thread[8]: Running on CPU0
|
||
Main[0]: Thread 8 created
|
||
Thread[2]: Now running on CPU0
|
||
Thread[3]: Now running on CPU0
|
||
Thread[4]: Now running on CPU0
|
||
Thread[3]: Now running on CPU2
|
||
Thread[3]: Now running on CPU0
|
||
Thread[5]: Now running on CPU1
|
||
Thread[5]: Now running on CPU0
|
||
Thread[6]: Calling pthread_barrier_wait()
|
||
Thread[8]: Calling pthread_barrier_wait()
|
||
Thread[3]: Calling pthread_barrier_wait()
|
||
Thread[5]: Calling pthread_barrier_wait()
|
||
Thread[1]: Calling pthread_barrier_wait()
|
||
Thread[2]: Now running on CPU2
|
||
Thread[2]: Calling pthread_barrier_wait()
|
||
Thread[7]: Now running on CPU3
|
||
Thread[4]: Now running on CPU1
|
||
Thread[4]: Calling pthread_barrier_wait()
|
||
Thread[7]: Calling pthread_barrier_wait()
|
||
Thread[7]: Back with ret=PTHREAD_BARRIER_SERIAL_THREAD (I AM SPECIAL)
|
||
Thread[6]: Back with ret=0 (I am not special)
|
||
Thread[8]: Back with ret=0 (I am not special)
|
||
Thread[3]: Back with ret=0 (I am not special)
|
||
Thread[5]: Back with ret=0 (I am not special)
|
||
Thread[1]: Back with ret=0 (I am not special)
|
||
Thread[2]: Back with ret=0 (I am not special)
|
||
Thread[4]: Back with ret=0 (I am not special)
|
||
Thread[7]: Now running on CPU1
|
||
Thread[6]: Now running on CPU2
|
||
Thread[3]: Now running on CPU1
|
||
Thread[5]: Now running on CPU2
|
||
Thread[1]: Now running on CPU1
|
||
Thread[4]: Now running on CPU3
|
||
Thread[2]: Now running on CPU0
|
||
Thread[7]: Now running on CPU0
|
||
Thread[6]: Now running on CPU0
|
||
Thread[3]: Now running on CPU0
|
||
Thread[4]: Now running on CPU0
|
||
Thread[1]: Now running on CPU0
|
||
Thread[5]: Now running on CPU0
|
||
Thread[3]: Now running on CPU3
|
||
Thread[3]: Now running on CPU0
|
||
Thread[4]: Now running on CPU2
|
||
Thread[3]: Done
|
||
Thread[4]: Now running on CPU0
|
||
Thread[4]: Done
|
||
Thread[7]: Done
|
||
Thread[2]: Done
|
||
Thread[5]: Now running on CPU2
|
||
Thread[8]: Now running on CPU1
|
||
Thread[8]: Done
|
||
Thread[6]: Now running on CPU3
|
||
Thread[5]: Done
|
||
Thread[1]: Done
|
||
Main[0]: Now running on CPU1
|
||
Main[0]: Thread 1 completed with result=0
|
||
Main[0]: Thread 2 completed with result=0
|
||
Main[0]: Thread 3 completed with result=0
|
||
Main[0]: Thread 4 completed with result=0
|
||
Main[0]: Thread 5 completed with result=0
|
||
Thread[6]: Done
|
||
Main[0]: Now running on CPU0
|
||
Main[0]: Thread 6 completed with result=0
|
||
Main[0]: Thread 7 completed with result=0
|
||
Main[0]: Thread 8 completed with result=0
|
||
nsh>
|
||
|
||
NOTES:
|
||
|
||
1. See the notes for the nsh configuration. Since this configuration
|
||
is essentially the same all of those comments apply.
|
||
|
||
2. See the STATUS and SMP sections above for detailed SMP-related
|
||
issues. There are a some major problems with the current SMP
|
||
implementation.
|
||
|
||
knsh
|
||
---
|
||
This is a configuration of testing the BUILD_KERNEL configuration.
|
||
|
||
$ cd nuttx
|
||
$ ./tools/configure.sh sabre-6quad:knsh
|
||
$ make V=1 -j7
|
||
$ make export V=1
|
||
$ cd ../apps
|
||
$ ./tools/mkimport.sh -x ../nuttx/nuttx-export-*.zip
|
||
$ make import V=1
|
||
$ cd ../nuttx
|
||
$ qemu-system-arm -semihosting -M sabrelite -m 1024 -smp 4 -nographic -kernel ./nuttx
|
||
|
||
NuttShell (NSH) NuttX-10.2.0
|
||
nsh> uname -a
|
||
NuttX 10.2.0 31283faf71 Mar 1 2022 19:52:48 arm sabre-6quad
|
||
nsh> ps
|
||
PID GROUP PRI POLICY TYPE NPX STATE EVENT SIGMASK STACK USED FILLED COMMAND
|
||
0 0 0 FIFO Kthread N-- Ready 00000000 002024 000984 48.6% Idle Task
|
||
1 1 100 RR Task --- Running 00000000 002016 001232 61.1% /system/bin/init
|
||
nsh> free
|
||
total used free largest nused nfree
|
||
Umem: 1048224 3728 1044496 1038304 6 2
|
||
Kmem: 1065201424 10720 1065190704 1065190704 30 1
|
||
Page: 134217728 1122304 133095424 133095424
|
||
nsh> /system/bin/hello
|
||
Hello, World!!
|
||
nsh> /system/bin/getprime
|
||
Set thread priority to 10
|
||
Set thread policy to SCHED_RR
|
||
Start thread #0
|
||
thread #0 started, looking for primes < 10000, doing 10 run(s)
|
||
thread #0 finished, found 1230 primes, last one was 9973
|
||
Done
|
||
/system/bin/getprime took 1850 msec
|
||
|
||
knsh_smp
|
||
--------
|
||
This is a configuration of testing the BUILD_KERNEL and SMP configuration.
|
||
|
||
$ cd nuttx
|
||
$ ./tools/configure.sh sabre-6quad:knsh_smp
|
||
$ make
|
||
$ make export
|
||
$ cd ../apps
|
||
$ ./tools/mkimport.sh -x ../nuttx/nuttx-export-*.zip
|
||
$ make import
|
||
$ cd ../nuttx
|
||
$ qemu-system-arm -semihosting -M sabrelite -m 1024 -smp 4 -nographic -kernel ./nuttx
|
||
|
||
NuttShell (NSH) NuttX-10.3.0-RC2
|
||
nsh> uname -a
|
||
NuttX 10.3.0-RC2 d9e95a8f9b-dirty May 26 2022 23:39:42 arm sabre-6quad
|
||
nsh> ps
|
||
PID GROUP CPU PRI POLICY TYPE NPX STATE EVENT SIGMASK STACK USED FILLED COMMAND
|
||
0 0 0 0 FIFO Kthread N-- Assigned 00000000 002024 000880 43.4% CPU0 IDLE
|
||
1 1 1 0 FIFO Kthread N-- Running 00000000 002024 000664 32.8% CPU1 IDLE
|
||
2 2 2 0 FIFO Kthread N-- Running 00000000 002024 000664 32.8% CPU2 IDLE
|
||
3 3 3 0 FIFO Kthread N-- Running 00000000 002024 000664 32.8% CPU3 IDLE
|
||
4 4 0 100 RR Task --- Running 00000000 004064 001116 27.4% /system/bin/init
|
||
nsh> free
|
||
total used free largest nused nfree
|
||
Umem: 1048224 5872 1042352 1036256 9 2
|
||
Kmem: 1065247648 12800 1065234848 1065234768 45 3
|
||
Page: 134217728 1101824 133115904 133115904
|
||
nsh> hello
|
||
Hello, World!!
|
||
nsh> getprime 4
|
||
Set thread priority to 10
|
||
Set thread policy to SCHED_RR
|
||
Start thread #0
|
||
Start thread #1
|
||
thread #1 started, looking for primes < 10000, doing 10 run(s)
|
||
Start thread #2
|
||
thread #2 started, looking for primes < 10000, doing 10 run(s)
|
||
Start thread #3
|
||
thread #3 started, looking for primes < 10000, doing 10 run(s)
|
||
thread #0 started, looking for primes < 10000, doing 10 run(s)
|
||
thread #1 finished, found 1230 primes, last one was 9973
|
||
thread #2 finished, found 1230 primes, last one was 9973
|
||
thread #3 finished, found 1230 primes, last one was 9973
|
||
thread #0 finished, found 1230 primes, last one was 9973
|
||
Done
|
||
getprime took 1570 msec
|
||
nsh>
|