PinePhone: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Immibis (talk | contribs)
→‎Backlight: actually tested the backlight and added register values
Immibis (talk | contribs)
→‎Loading code example: SRAM A contains some stuff you can't overwrite
 
(5 intermediate revisions by the same user not shown)
Line 71:
sunxi-fel write 0x00010000 code.bin
sunxi-fel execute 0x00010000
 
Why 0x00010000? According to the [https://linux-sunxi.org/A64/Memory_map memory map] this region 0x00010000-0x00017FFF is where the boot ROM normally loads user code, which means it shouldn't conflict with anything used by the boot ROM (e.g. to support the USB interface).
 
Your code can execute BX LR to return back to the boot loader.
 
To see if your toolchain works you can try to run [[User:Immibis/PinePhone Blinky]].
 
Why 0x00010000? According to the [https://linux-sunxi.org/A64/Memory_map memory map] this region 0x00010000-0x00017FFF is where the boot ROM normally loads user code, <s>which means it shouldn't conflict with anything used by the boot ROM (e.g. to support the USB interface).</s> region 0x00010XXX is fine, 0x00011XXX conflicts and breaks USB. Comments in the sunxi-fel tool indicate regions 0x11c00-0x11fff (IRQ stack), 0x15c00-0x16fff (actual stack), and 0x17c00-0x17fff ("something important", probably USB-related data structures or similar) are important. Additionally, the tool uses 0x31400-0x32fff to hold backup copies of these.
It can also use 0x11000-0x113FF to hold code and data for more complex commands.
 
Maybe 0x18000 (SRAM C) is a good load location. 0x19400 bytes (~48k) should be available.
If using SRAM C, don't set 0x01C202C4 (Bus Clock Register1) bit 0x00000001 (Gating Clock VE) to 0 as this seems to make SRAM C inaccessible. I guess it's connected to the video engine?
 
Alternatively you could initialize DRAM and then load your code into DRAM, as two separate steps.
 
== Custom bootloader stuff ==
Line 87 ⟶ 93:
 
== Power distribution ==
As this is a battery-powered device you probably want to be aware of what is powered up at any given time. Turning off chips you're not using will make the battery last longer! It looks like all the big power users are off by default, anyway.
 
As this is a battery-powered device, power is a big issue. The system has no less than ''eighteen'' power supplies which can be turned on and off individually and have adjustable voltages. These are all controlled by the AXP803 power management chip, which also manages the battery detection and charging. There are a few power rails not controlled by the AXP803, such as the USB power output (not input).
If some hardware isn't working, find it in the schematic and make sure all its power sources are turned on. The AXP803 power manager is connected to the CPU via an I2C bus. (TODO: Is any communication actually needed or is everything on by default?)
 
Turning off chips you're not using will make the battery last longer! But at the beginning you probably need to turn things ''on''. The display screen is not powered by default.
 
[https://raw.githubusercontent.com/OLIMEX/OLINUXINO/master/DOCUMENTS/A64-PDFs/AXP803_Datasheet_V1.0.pdf AXP830 datasheet]
 
The AXP803 can be accessed by the S-TWI interface located on GPIOs PL0 and PL1. The TWI interface block hasn't been explored yet, but you can write bit-banging code using the GPIO. For details how to access those GPIOs see the. Note that I2C is an open-drain protocol, so you should switch the pins between input mode and output-0 mode. Setting them to output 1 has a small chance of damaging either the CPU or the AXP due to a logic level conflict, so don't do it. Because it's open-drain you should also enable pull-up resistors on the CPU side. (Actually it's not clear whether the AXP already has built-in pullups. Having two sets doesn't hurt, but it might waste a little bit of power)
 
'''Before accessing PL0/PL1''' you must enable bit 0 (0x00000001) in register 0x01F01428. Port PL is on a separate section of the CPU from all the other GPIO ports. This bit enables the clock to this section. Otherwise the section ignores register writes.
 
The AXP803's I2C address is 0x68 (write) / 0x69 (read) / 0x34 (7-bit address format).
 
You can write a register by writing the register number and then the value (that's start signal, send 0x68, send register number, send value, stop signal). You can read a register by writing the register number and then reading the value (start signal, send 0x68, send register number, repeated start signal, send 0x69, read value, stop signal). Remember that when changing I2C transfer direction, you should send a repeated start condition and send the device address again (with the new direction). After reading one register, send ACK if you want to read the next register or NACK if you want to finish. If you send ACK and then stop, the chip's I2C interface will be left in a weird state and you'll have to . If you keep reading bytes after the first one, you read the next register, and the next.
 
Registers 0x00-0x03 are useful to see if your reading code works correctly; registers 0x04-0x0F are scratch registers with no purpose which you can write and then read to test the writing.
 
== List of built-in peripherals ==
Line 211 ⟶ 229:
| Red || 0x00080000 || PD19
|-
| Green || 0x001000000x00040000 || PD20PD18
|-
| Blue || 0x000400000x00100000 || PD18PD20
|-
| Rumble motor || 0x00000004 || PD2
|}
 
 
==== Sensors ====