https://www.3dbrew.org/w/api.php?action=feedcontributions&user=Profi200&feedformat=atom
3dbrew - User contributions [en]
2024-03-28T14:23:38Z
User contributions
MediaWiki 1.35.8
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=21485
SPI Registers
2021-02-14T23:09:41Z
<p>Profi200: /* NSPI_FIFO */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]1<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]1<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]1<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]1<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]1<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]1<br />
| 0x10142814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]1<br />
| 0x10142818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]1<br />
| 0x1014281C<br />
| 4<br />
| -<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]2<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]2<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]2<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]2<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]2<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]2<br />
| 0x10143814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]2<br />
| 0x10143818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]2<br />
| 0x1014381C<br />
| 4<br />
| -<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]3<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA3<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]3<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]3<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]3<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]3<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]3<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]3<br />
| 0x10160814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]3<br />
| 0x10160818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]3<br />
| 0x1016081C<br />
| 4<br />
| -<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== NSPI_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Clock<br />
|-<br />
| 6-7<br />
| Device select<br />
|-<br />
| 12<br />
| Bus mode (0 = 1 bit, 1 = 4 bit)<br />
|-<br />
| 13<br />
| Transfer direction (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| 1 = Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Bus<br />
! Device select<br />
! Clock<br />
|-<br />
| 0<br />
| 3<br />
| 0<br />
| 2<br />
|-<br />
| 1, 2<br />
| 3<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 3<br />
| 1<br />
| 0<br />
| 5<br />
|-<br />
| 4, 5<br />
| 1<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 6<br />
| 2<br />
| 0<br />
| ?<br />
|}<br />
<br />
== NSPI_DONE ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Chip select<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
32-bit FIFO for reading/writing the SPI payload. This FIFO is one way (half-duplex).<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO full (0 = not full, 1 = full)<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
At transfer start and every 32 bytes the FIFO becomes busy.<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Clock (from [[#NSPI_CNT|NSPI_CNT]]) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (also fires on each autopoll try?)<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[ARM11_Interrupts#Hardware_Interrupts|Interrupt]] ID 0x24, 0x56 or 0x57 (depending on the bus) is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=21484
SPICARD Registers
2021-02-14T23:08:11Z
<p>Profi200: /* NSPI_FIFO */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! RW<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]<br />
| 0x1000D800<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]<br />
| 0x1000D804<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]<br />
| 0x1000D808<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]<br />
| 0x1000D80C<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]<br />
| 0x1000D810<br />
| 4<br />
| R<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]<br />
| 0x1000D814<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]<br />
| 0x1000D818<br />
| 4<br />
| W?<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]<br />
| 0x1000D81C<br />
| 4<br />
| RW<br />
|<br />
|}<br />
<br />
== NSPI_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-2<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading this register.<br />
<br />
== NSPI_DONE ==<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
This FIFO is one way (half-duplex).<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs. Nintendo uses a timeout of 10 which roughly equals 1 second. This is used in Process9 to poll the gamecard SPI flash status register for write operation finished or write enable.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (also fires on each autopoll try?)<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[IRQ_Registers|Interrupt]] ID 23 is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=Gamecards&diff=21482
Gamecards
2021-02-13T01:13:30Z
<p>Profi200: /* SPI flash */ Clock polarity and phase.</p>
<hr />
<div>[[File:Gamecard.jpg|thumb|right|A 3DS gamecard]] <br />
[[File:GamecardPhy.jpg|thumb|right|Close-up of PCB]] <br />
<br />
===Physical interface===<br />
The 3DS gamecards have the same physical interface as regular DS and DSi gamecards. There is only a minor cosmetic difference in the plastic case, which has a small extruding notch on the top-right side. As such, it prevents insertion of the gamecard into old Nintendo DS or DSi systems. <br />
<br />
When modifying the case so that the 3DS gamecard fits in a DS or DSi system, those systems will refuse to detect the gamecard and show no banner icon.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Pin<br />
! Name<br />
! Description<br />
|-<br />
| 1<br />
| GND<br />
| Ground<br />
|-<br />
| 2<br />
| CLK<br />
| Clock. Frequencies 6.7MHz and 4.2MHz for DS/DSi gamecards, up to 16.6MHz for 3DS gamecards (for both SPI and ROM transfers).<br />
|-<br />
| 3<br />
| NC<br />
| Not connected. Possibly used to program cards.<br />
|-<br />
| 4<br />
| RCS<br />
| ROM select, active low. Pulled low to start a ROM transfer.<br />
|-<br />
| 5<br />
| RST<br />
| Reset, active low. <br />
|-<br />
| 6<br />
| ECS<br />
| Savegame chip select, active low. Pulled low to start a savegame SPI transfer.<br />
|-<br />
| 7<br />
| IRQ<br />
| Removal detection.<br />
|-<br />
| 8<br />
| VCC<br />
| Powersupply 3.3V.<br />
|-<br />
| 9<br />
| DAT0<br />
| Bidirectional data bus.<br />
|-<br />
| 10<br />
| DAT1<br />
| Bidirectional data bus.<br />
|-<br />
| 11<br />
| DAT2<br />
| Bidirectional data bus.<br />
|-<br />
| 12<br />
| DAT3<br />
| Bidirectional data bus.<br />
|-<br />
| 13<br />
| DAT4<br />
| Bidirectional data bus / pin NC/SIO3 on savegame chip.<br />
|-<br />
| 14<br />
| DAT5<br />
| Bidirectional data bus / pin WP#/SIO2 on savegame chip.<br />
|-<br />
| 15<br />
| DAT6<br />
| Bidirectional data bus / pin SO/SIO1 on savegame chip.<br />
|-<br />
| 16<br />
| DAT7<br />
| Bidirectional data bus / pin SI/SIO0 on savegame chip.<br />
|-<br />
| 17<br />
| GND<br />
| Ground<br />
|}<br />
<br />
===SPI flash===<br />
Savegame SPI flash transfers use CPOL=1 and CPHA=1. So far, only one savegame FLASH chip has been identified. The chip identifies as a 0xC22211. The JEDEC manufacturer ID is Macronix, and despite the chip label saying 25L1001, the JEDEC ID matches the MX25L1021E. Datasheet at:<br><br />
http://www.macronix.com/QuickPlace/hq/PageLibrary4825740B00298A3B.nsf/$defaultview/3F21BAC2E121E17848257639003A3146/$File/MX25L1021E%2C%203V%2C%201Mb%2C%20v1.1.pdf?OpenElement <br><br />
http://www.beilenet.com/download/MX25L1021E,%203V,%201Mb,%20v0.01.pdf (old version mirror) <br><br />
However, the MX25L1021E doesn't support the 4 bit wide transmission that the 3DS uses to talk to the SPI flash. It is thus likely that this is a custom flash chip.<br />
<br />
===Format===<br />
Cartridges can come in several sizes and include system updates in a region reserved for this. In ROMs less than 1GB the update region can be found with:<br />
CART_SIZE_MAX-( 0x280000*(CART_SIZE_MAX/CART_SIZE_128MB) )-0x2000000. The region is then 0x2000000 bytes.<br />
<br />
===Protocol===<br />
The communication protocol between the 3DS system and the 3DS gamecard has changed almost completely in comparison with the [http://problemkaputt.de/gbatek.htm#dscartridgeprotocol DS and DSi gamecard communication protocol].<br />
<br />
After the sixth transfer, commands change size from 8 bytes to 16 bytes. Possibly a new encryption is used, such as AES CTR.<br />
When 16-byte commands are used, the data bus maintains the value 0x00 until the card signals it is ready by clocking a single byte 0x01, followed by the actual data. After each 0x200-byte block of actual data, a 4-byte standard CRC32 of the block data (before encryption) follows.<br />
<br />
Here's a set of sample gamecard commands that a 3DS sends to a 3DS gamecard:<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Size<br />
! Command<br />
! Decrypted command<br />
! Description<br />
|-<br />
|<tt>2000</tt><br />
|<tt>9F00000000000000</tt><br />
|?<br />
|Reset<br />
|-<br />
|<tt>0000</tt><br />
|<tt>71C93FE9BB0A3B18</tt><br />
|?<br />
|Unknown<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9000000000000000</tt><br />
|?<br />
|Get gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9000000000000000</tt><br />
|?<br />
| Get gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>A000000000000000</tt><br />
|?<br />
| Unknown, response=00000000<br />
|-<br />
|<tt>0000</tt><br />
|<tt>3E00000000000000</tt><br />
|?<br />
| Enter 16-byte command mode.<br />
|-<br />
|<tt>0200</tt><br />
|<tt>82000000000000000000000000000000</tt><br />
|?<br />
| Get header<br />
|-<br />
|<tt>0000</tt><br />
|<tt>F32C92D85C9D44DED3E0E41DBE7C90D9</tt><br />
|<tt>8300000000000000708DF1A731717D0B</tt> <br />
| Seed<br />
|-<br />
|<tt>0004</tt><br />
|<tt>696B9D8582FB55D31B68CAFE70C74A95</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>BAA4812CA0AC9C5D19399530E3ACCCAB</tt><br />
|<tt>A300000000000000708DF1A731717D0B</tt><br />
| Unknown<br />
|-<br />
|<tt>0000</tt><br />
|<tt>178E427C22D87ADB86387249A97D321A</tt><br />
|<tt>C500000000000000708DF1A731717D0B</tt><br />
| Unknown<br />
|-<br />
|<tt>0004</tt><br />
|<tt>E06019B1BD5C9130ED6A4D9F4A9E7193</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>4E0D224862523BBFE2E6255F80E15F37</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>4CDF93D319FB62D0DB632A45E3E8D84C</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>9AA5D80551002F955546D296A57F0FEF</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0004</tt><br />
|<tt>C12BA81AEF30DDDBD93FAD5D544C6334</tt><br />
|<tt>A200000000000000708DF1A731717D0B</tt><br />
| Get secured gamecard ID, response=9000FEC2<br />
|-<br />
|<tt>0200</tt><br />
|<tt>62EC5FB7F420AE1DC6253AE18AFA5BB3</tt><br />
|<tt>BF000000000000000000000000000000</tt><br />
| Read address 0<br />
|-<br />
|<tt>0200</tt><br />
|<tt>E3FA23AA016BE0C93430D1F42FF41324</tt><br />
|<tt>BF000000000040000000000000000000</tt><br />
| Read address 0x4000<br />
|}<br />
<br />
The header command has some initial dummy bytes, and eventually responds with a 0x200 byte header. Here's an example for Lego Starwars 3:<br />
0000000: 00 8c 03 00 00 00 04 00 00 00 00 00 00 00 00 00 ................<br />
0000010: b3 cf fb c6 6a b1 cb 20 32 af ce 35 d4 1c 74 c9 ....j.. 2..5..t.<br />
0000020: 8e 6b 27 2f 08 01 28 3b d4 30 de 44 37 f5 b0 46 .k'/..(;.0.D7..F<br />
0000030: 91 59 d7 38 33 48 df 83 fd 71 84 2c 00 00 00 00 .Y.83H...q.,....<br />
0000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000100: 4e 43 43 48 7a 7f 0e 00 00 8c 03 00 00 00 04 00 NCCHz...........<br />
0000110: 36 34 02 00 00 00 00 00 00 8c 03 00 00 00 04 00 64..............<br />
0000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................<br />
0000150: 43 54 52 2d 50 2d 41 4c 47 50 00 00 00 00 00 00 CTR-P-ALGP......<br />
0000160: 0c 27 e3 c1 de 7b 2a e2 d3 11 4f 32 a4 ee bf 46 .'...{*...O2...F<br />
0000170: 9a fd 0c f3 52 c1 1d 49 84 c2 a9 f1 d2 14 4c 63 ....R..I......Lc<br />
0000180: 00 04 00 00 00 00 00 00 00 00 00 00 01 03 00 00 ................<br />
0000190: 05 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................<br />
00001a0: 06 00 00 00 1c 0a 00 00 01 00 00 00 00 00 00 00 ................<br />
00001b0: 22 0a 00 00 58 75 0e 00 01 00 00 00 00 00 00 00 "...Xu..........<br />
00001c0: 13 0c 04 26 15 f6 47 c4 c6 32 25 ea 9e 67 f8 a2 ...&..G..2%..g..<br />
00001d0: 7b 15 24 6b 88 fb c7 a9 27 25 7b 84 97 7b 78 7b {.$k....'%{..{x{<br />
00001e0: a6 5b ee 10 60 bb 6a 68 21 bb ce c6 00 03 5b 7e .[..`.jh!.....[~<br />
00001f0: 64 fb 6e ac a7 f0 96 0c fb 1f 5a 37 08 77 28 f7 d.n.......Z7.w(.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=Corelink_DMA_Engines&diff=21473
Corelink DMA Engines
2021-01-29T12:51:36Z
<p>Profi200: /* XDMA Peripheral IDs */</p>
<hr />
<div>XDMA cannot access the ARM9 bootrom at all.<br />
<br />
==DmaConfig==<br />
Size of struct is 24 bytes.<br />
<br />
struct DmaConfig {<br />
sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care.<br />
uint8_t endian_swap_size; // @1 Accepted values: 0=none, 2=16bit, 4=32bit, 8=64bit.<br />
uint8_t flags; // @2 bit0: SRC_IS_PERIPHERAL, bit1: DST_IS_PERIPHERAL, bit2: SHALL_BLOCK, bit3: KEEP_ALIVE, bit6: SRC_IS_RAM, bit7: DST_IS_RAM<br />
uint8_t padding;<br />
DmaSubConfig dst_cfg;<br />
DmaSubConfig src_cfg;<br />
}<br />
<br />
struct DmaSubConfig {<br />
sint8_t peripheral_id; // @0 If not *_IS_RAM set, this must be < 0x1E.<br />
uint8_t allowed_burst_sizes; // @1 Accepted values: 4, 8, 4|8 = 12, 1|2|4|8 = 15 <br />
sint16_t gather_granule_size; // @2<br />
sint16_t gather_stride; // @4 Has to be >= 0, must not be 0 if peripheral_id == 0xFF.<br />
sint16_t scatter_granule_size; // @6<br />
sint16_t scatter_stride; // @8 Can be negative.<br />
}<br />
<br />
If SRC_IS_PERIPHERAL/SRC_IS_PERIPHERAL is set in the flags field, the configuration for src/dst is loaded from src_cfg/dst_cfg respectively and the transfer will be done from/to a fixed address. If the *_IS_RAM flag is set same thing goes, except byte0 of each cfg is forced to 0xFF (RAM) and the transfer will be done from/to an incrementing address. *_IS_RAM has priority over _IS_PERIPHERAL.<br />
<br />
If neither *_IS_PERIPHERAL or *_IS_RAM is set, default configuration is loaded:<br />
<br />
.peripheral_id = 0xFF,<br />
.allowed_burst_sizes = 1 | 2 | 4 | 8,<br />
.gather_granule_size = 0x80,<br />
.gather_stride = 0,<br />
.scatter_granule_size = 0x80,<br />
.scatter_stride = 0,<br />
<br />
If SHALL_BLOCK is set, the thread will sleep until the DMA engine is ready. If not set, the SVC will return 0xD04007F0 if the DMA channel is busy.<br />
<br />
The generated bytecode starts with a FLUSHP on the peripheral_ids for src/dst (if specified). After that, it always moves 0 into DAR. Then it moves the src/dst addresses into SAR/DAR respectively...<br />
<br />
== CDMA Peripheral IDs ==<br />
<br />
{| class="wikitable" border="1"<br />
! ID<br />
! Module<br />
! Description<br />
|-<br />
| 0x2<br />
| camera (cam)<br />
| Camera Port 1<br />
|-<br />
| 0x3<br />
| camera (cam)<br />
| Camera Port 2<br />
|-<br />
| 0x4<br />
| nwm<br />
| ?<br />
|-<br />
| 0x5<br />
| nwm<br />
| ?<br />
|-<br />
| 0x6<br />
| camera (y2r)<br />
| SetSendingY<br />
|-<br />
| 0x7<br />
| camera (y2r)<br />
| SetSendingU<br />
|-<br />
| 0x8<br />
| camera (y2r)<br />
| SetSendingV<br />
|-<br />
| 0x9<br />
| camera (y2r)<br />
| SetSendingYUYV<br />
|-<br />
| 0xA<br />
| camera (y2r)<br />
| SetReceiving<br />
|-<br />
| 0xB<br />
| fs<br />
| HASH<br />
|-<br />
| 0xD<br />
| TwlBg<br />
| LGYFB0/1<br />
|-<br />
| 0xE<br />
| TwlBg<br />
| LGYFB0/1<br />
|-<br />
| 0x12<br />
| mvd (y2r2)<br />
| SetSendingY<br />
|-<br />
| 0x13<br />
| mvd (y2r2)<br />
| SetSendingU<br />
|-<br />
| 0x14<br />
| mvd (y2r2)<br />
| SetSendingV<br />
|-<br />
| 0x15<br />
| mvd (y2r2)<br />
| SetSendingYUV<br />
|-<br />
| 0x16<br />
| mvd (y2r2)<br />
| SetReceiving<br />
|-<br />
| 0x17<br />
| mvd<br />
| Related to l2b<br />
|-<br />
| 0x18<br />
| mvd<br />
| Related to l2b<br />
|-<br />
| 0x19<br />
| mvd<br />
| Related to l2b<br />
|-<br />
| 0x1A<br />
| mvd<br />
| Related to l2b<br />
|}<br />
<br />
== XDMA Peripheral IDs ==<br />
<br />
{| class="wikitable" border="1"<br />
! ID<br />
! Module<br />
! Description<br />
|-<br />
| 0<br />
| Process9<br />
| CTRCARD1 (0x10004000?)<br />
|-<br />
| 1<br />
| ?<br />
| CTRCARD2 (0x10005000?)<br />
|-<br />
| 2<br />
| ?<br />
| TMIO1 (0x10006000)<br />
|-<br />
| 3<br />
| ?<br />
| TMIO3 (0x10007000)<br />
|-<br />
| 4<br />
| ?<br />
| AES in<br />
|-<br />
| 5<br />
| ?<br />
| AES out<br />
|-<br />
| 6<br />
| ?<br />
| SHA in<br />
|-<br />
| 7<br />
| Process9<br />
| SHA out<br />
|-<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=21261
CONFIG9 Registers
2020-05-28T13:29:01Z
<p>Profi200: /* CFG9_SDMMCCTL */ Oops</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDMMCCTL|CFG9_SDMMCCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| 1 = Switch to [[SPICARD_Registers|SPICARD]] interface (savegames).<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDMMCCTL ==<br />
This register controls power of multiple ports/controllers and allows to map controller 3 to ARM9 or ARM11. The SD card can be accessed on ARM11 by setting bit 8 and clearing bit 9.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Controller 1/3 port 0 power (SD card) (1=off)<br />
| Process9<br />
|-<br />
| 1<br />
| Controller 1 port 1 power (eMMC) (1=off)<br />
| Process9<br />
|-<br />
| 2<br />
| Controller 2 port 0 power (WiFi SDIO) (1=off)<br />
| Process9<br />
|-<br />
| 3<br />
| Controller 3 port 1 power? Set at cold boot.<br />
| -<br />
|-<br />
| 4-5<br />
| Unused.<br />
| -<br />
|-<br />
| 6<br />
| Wifi port related? Pull up? Set at cold boot.<br />
| -<br />
|-<br />
| 8<br />
| Controller 3 mapping (0=ARM9 0x10007000, 1=ARM11 0x10100000)<br />
| Process9<br />
|-<br />
| 9<br />
| SD card controller select (0=0x10007000/0x10100000, 1=0x10006000)<br />
| Process9<br />
|-<br />
| 10-15<br />
| Unused.<br />
| -<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21260
CONFIG11 Registers
2020-05-27T22:33:28Z
<p>Profi200: /* LGY_MODE */ Oops.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_PDN_CNT<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PDN_WAKE_ENABLE<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PDN_WAKE_REASON<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_FCRAM_CNT followed by 1 and waiting for bit 2 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
Also named "KEYCNT" on certain other DS(i)/GBA documentations.<br />
The value of this register is copied to [[HID_Registers|HID_PADCNT]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=IO_Registers&diff=21259
IO Registers
2020-05-27T22:25:56Z
<p>Profi200: /* Overview */</p>
<hr />
<div>= Overview =<br />
<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! A9/A11<br />
! Category<br />
! Physaddr<br />
! Used by<br />
! Comments<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[CONFIG9 Registers]]<br />
| 0x10000000<br />
| Boot9, Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[IRQ Registers]]<br />
| 0x10001000<br />
| Boot9, Process9, Kernel9<br />
| ARM9 Interrupt Masking<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[NDMA Registers]]<br />
| 0x10002000<br />
| Boot9, Process9<br />
| DMA Engine<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[TIMER Registers]]<br />
| 0x10003000<br />
| Boot9, Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[CTRCARD Registers]]<br />
| 0x10004000 / 0x10005000<br />
| Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[EMMC Registers]]<br />
| 0x10006000 / 0x10007000<br />
| Boot9, Process9, NewKernel9Loader<br />
| SD(IO) controller 1 and 3. 3 is normally mapped to ARM11.<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[PXI Registers]]<br />
| 0x10008000<br />
| Boot9, Process9<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[AES Registers]]<br />
| 0x10009000<br />
| Boot9, Process9, NewKernel9Loader<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[SHA Registers]]<br />
| 0x1000A000<br />
| Boot9, Process9, NewKernel9Loader<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[RSA Registers]]<br />
| 0x1000B000<br />
| Boot9, Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[Corelink DMA Engines|XDMA Registers]]<br />
| 0x1000C000<br />
| Boot9, Kernel9<br />
| [http://infocenter.arm.com/help/topic/com.arm.doc.subset.primecell.system/index.html CoreLinkâ„¢ DMA-330 r0p0] (two channels).<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[SPICARD Registers]]<br />
| 0x1000D800<br />
| Process9<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A9<br />
| [[CONFIG Registers]]<br />
| 0x10010000<br />
| Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| PRNG Registers<br />
| 0x10011000<br />
| Boot9, Process9<br />
| Used as entropy-source for seeding random number generators.<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[OTP Registers]]<br />
| 0x10012000<br />
| Boot9, Kernel9, NewKernel9Loader<br />
| Top secret.<br />
|-<br />
| style="background: green" | Yes<br />
| A9<br />
| [[ARM7|ARM7 Registers]]<br />
| 0x10018000<br />
| TwlProcess9<br />
| Used to setup the ARM7 core for AGB/TWL<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| TMIO SD(IO) controller 3<br />
| 0x10100000<br />
| <br />
| NWM references this controller but doesn't have access to it.<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[HASH Registers]]<br />
| 0x10101000<br />
| [[Filesystem services]]<br />
| These registers function the same as the [[SHA Registers]], with the exception of the FIFO being located at 0x10301000.<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[Y2R Registers]]<br />
| 0x10102000<br />
| [[Camera Services]]<br />
| y2r<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[CSND Registers]]<br />
| 0x10103000<br />
| TwlBg, [[Codec Services]], [[CSND Services]], [[DSP Services]]<br />
| Sound hardware.<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MTX_Registers|LgyFb bottom screen]]<br />
| 0x10110000<br />
| TwlBg<br />
| IO registers used to access legacy output framebuffer, as well as configure the upscaling filter.<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MTX_Registers|LgyFb top screen]]<br />
| 0x10111000<br />
| TwlBg<br />
| IO registers used to access legacy output framebuffer, as well as configure the upscaling filter.<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[Camera Registers]] <br />
| 0x10120000<br />
| [[Camera Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[Camera Registers]]<br />
| 0x10121000<br />
| [[Camera Services]]<br />
| Mirror of 0x10120000?<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[WIFI Registers]]<br />
| 0x10122000<br />
| [[NWM Services]]<br />
| WIFI SDIO bus registers<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| ?<br />
| 0x10123000<br />
| [[NWM Services]]<br />
| WIFI?<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| A11/A9<br />
| [[MVD Registers]]<br />
| 0x10130000<br />
| [[MVD Services]]<br />
| <br />
|-<br />
| style="background: red" | No<br />
| A11/A9<br />
| [[MVD Registers]]<br />
| 0x10131000<br />
| [[MVD Services]]<br />
| <br />
|-<br />
| style="background: red" | No<br />
| A11/A9<br />
| [[MVD Registers]]<br />
| 0x10132000<br />
| [[MVD Services]]<br />
| <br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[CONFIG11 Registers]]<br />
| 0x10140000<br />
| Process9, Boot11, Kernel11, TwlBg, [[DSP Services]], [[NWM Services]], [[SPI Services]]<br />
| Power management. <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[CONFIG11 Registers]]<br />
| 0x10141000<br />
| Process9, Boot11, Kernel11, TwlBg, [[Codec Services]], [[NWM Services]], [[SPI Services]], [[PDN Services]]<br />
| Power management<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[SPI Registers]]<br />
| 0x10142000<br />
| TwlBg, [[SPI Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[SPI Registers]]<br />
| 0x10143000<br />
| TwlBg, dmnt Module<br />
| Debugger related?<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[I2C Registers]]<br />
| 0x10144000<br />
| Boot11, Kernel11, TwlBg, [[I2C Services]]<br />
| 3DS I2C interface (MCU + Cameras + LCD)<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[CODEC Registers]]<br />
| 0x10145000<br />
| TwlBg, [[Codec Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[HID Registers]]<br />
| 0x10146000<br />
| Boot9, Boot11, Kernel11, TwlBg, [[HID Services]], dlp Services<br />
| See [[PAD]].<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[GPIO Registers]]<br />
| 0x10147000<br />
| Boot11, TwlBg, [[GPIO Services]], [[DSP Services]](v0)<br />
| <br />
|- <br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[I2C Registers]]<br />
| 0x10148000<br />
| TwlBg, [[I2C Services]]<br />
| 3DS I2C interface (Gyro + IR)<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[SPI Registers]]<br />
| 0x10160000<br />
| Boot9, TwlBg, [[SPI Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[I2C Registers]]<br />
| 0x10161000<br />
| Boot11, TwlBg, [[I2C Services]]<br />
| TWL I2C interface (MCU + Cameras)<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MIC Registers]]<br />
| 0x10162000<br />
| [[MIC Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[PXI Registers]]<br />
| 0x10163000<br />
| Boot11, Kernel11, TwlBg, [[PXI Services]]<br />
| <br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[NTRCARD Registers]]<br />
| 0x10164000<br />
| Boot9, Process9<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10165000<br />
| [[MP Services]]<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10170000<br />
| [[MP Services]]<br />
| NTR WIFI Registers, see [http://problemkaputt.de/gbatek.htm#dswirelesscommunications GBATek].<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10171000<br />
| [[MP Services]]<br />
| NTR WIFI Registers (mirror)<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
|?<br />
| 0x10172000<br />
|?<br />
| NTR WIFI Unused?<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
|?<br />
| 0x10173000<br />
|?<br />
| NTR WIFI Unused?<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10174000<br />
| [[MP Services]]<br />
| NTR WIFI RAM<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10175000<br />
|?<br />
| NTR WIFI RAM<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10176000<br />
|?<br />
| NTR WIFI Registers (mirror)<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10177000<br />
|?<br />
| NTR WIFI Registers (mirror)<br />
|-<br />
| style="background: green" | Yes<br />
| A11/A9<br />
| [[MP Registers]]<br />
| 0x10178000 - 0x10180000<br />
| [[MP Services]]<br />
| NTR WIFI WS1 Region<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11<br />
| [[Corelink DMA Engines|CDMA]]<br />
| 0x10200000<br />
| Boot11, Kernel11<br />
| [http://infocenter.arm.com/help/topic/com.arm.doc.subset.primecell.system/index.html CoreLinkâ„¢ DMA-330 r0p0] (eight channels). Only used by bootrom on New3DS.<br />
|-<br />
| style="background: green" | Yes<br />
| A11<br />
| ?<br />
| 0x10201000<br />
| TwlBg<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A11<br />
| [[LCD Registers]]<br />
| 0x10202000<br />
| TwlBg, Kernel11, [[GSP Services]]<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| A11<br />
| [[DSP Registers]]<br />
| 0x10203000<br />
| [[DSP Services]]<br />
| see the "DSi XpertTeak" section in [http://problemkaputt.de/gba.htm no$gba] help.<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| A11<br />
| ?<br />
| 0x10204000<br />
| ?<br />
| <br />
|-<br />
| style="background: red" | No<br />
| A11<br />
| [[Corelink DMA Engines|CDMA]]<br />
| 0x10206000<br />
| NewKernel11<br />
| [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0424d/index.html CoreLinkâ„¢ DMA-330 r1p2] (eight channels). This is the DMA engine actually being used by the New3DS ARM11 kernel.<br />
|-<br />
| style="background: red" | No<br />
| A11<br />
| [[MVD Registers]]<br />
| 0x10207000<br />
| [[MVD Services]]<br />
| New 3DS only?<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11<br />
| AXI<br />
| 0x1020F000<br />
| TwlBg, [[GSP Services]]<br />
| [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0422a/CHDGHIID.html CoreLinkâ„¢ NIC-301 r1p0].<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11<br />
| DMA region<br />
| 0x10300000-0x10400000<br />
|<br />
| CDMA wants these addresses. Most pages in this region correspond to the same respective pages in the 0x10100000-0x10200000 region. The HASH FIFO register is located at 0x10301000 only.<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| A11<br />
| [[GPU/External_Registers|GPU Registers]]<br />
| 0x10400000<br />
| Boot11, Kernel11, [[GSP Services]]<br />
||<br />
|}<br />
<br />
IO registers starting at physical address 0x10200000 are not accessible from the ARM9 (which includes all LCD/GPU registers). It seems IO registers below physical address 0x10100000 are not accessible from the ARM11 bus.<br />
<br />
ARM11 kernel virtual address mappings for these registers varies for different builds. For ARM11 user mode applications you have:<br />
physaddr = virtaddr - 0x1EC00000 + 0x10100000</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=21258
CONFIG9 Registers
2020-05-27T22:18:29Z
<p>Profi200: /* CFG9_SDMMCCTL */ ARM11 SD card access hype.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDMMCCTL|CFG9_SDMMCCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| 1 = Switch to [[SPICARD_Registers|SPICARD]] interface (savegames).<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDMMCCTL ==<br />
This register controls power of multiple ports/controllers and allows to map controller 3 to ARM9 or ARM11. The SD card can be accessed on ARM11 by clearing bit 8 and 9.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Controller 1/3 port 0 power (SD card) (1=off)<br />
| Process9<br />
|-<br />
| 1<br />
| Controller 1 port 1 power (eMMC) (1=off)<br />
| Process9<br />
|-<br />
| 2<br />
| Controller 2 port 0 power (WiFi SDIO) (1=off)<br />
| Process9<br />
|-<br />
| 3<br />
| Controller 3 port 1 power? Set at cold boot.<br />
| -<br />
|-<br />
| 4-5<br />
| Unused.<br />
| -<br />
|-<br />
| 6<br />
| Wifi port related? Pull up? Set at cold boot.<br />
| -<br />
|-<br />
| 8<br />
| Controller 3 mapping (0=ARM9 0x10007000, 1=ARM11 0x10100000)<br />
| Process9<br />
|-<br />
| 9<br />
| SD card controller select (0=0x10007000/0x10100000, 1=0x10006000)<br />
| Process9<br />
|-<br />
| 10-15<br />
| Unused.<br />
| -<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=GPU/External_Registers&diff=21228
GPU/External Registers
2020-05-07T13:53:40Z
<p>Profi200: /* LCD Source Framebuffer Setup */ Forgot to mention which screen.</p>
<hr />
<div>This page describes the address range accessible from the ARM11, used to configure the basic GPU functionality. For information about the internal registers used for 3D rendering, see [[GPU/Internal Registers]].<br />
<br />
== Map ==<br />
Address mappings for the external registers. GSPGPU:WriteHWRegs takes these addresses relative to 0x1EB00000. <br />
{| class="wikitable" border="1"<br />
! User VA<br />
! PA<br />
! Length<br />
! Name<br />
! Comments<br />
|-<br />
| 0x1EF00004<br />
| 0x10400004<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00010<br />
| 0x10400010<br />
| 16<br />
| [[#Memory Fill|Memory Fill1]] "PSC0"<br />
| GX command 2<br />
|-<br />
| 0x1EF00020<br />
| 0x10400020<br />
| 16<br />
| [[#Memory Fill|Memory Fill2]] "PSC1"<br />
| GX command 2<br />
|-<br />
| 0x1EF00030<br />
| 0x10400030<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00034<br />
| 0x10400034<br />
| 4<br />
| GPU Busy<br />
| Bit31 = cmd-list busy, bit27 = PSC0 busy, bit26 = PSC1 busy.<br />
|-<br />
| 0x1EF00050<br />
| 0x10400050<br />
| 4<br />
| ?<br />
| Writes 0x22221200 on GPU init.<br />
|-<br />
| 0x1EF00054<br />
| 0x10400054<br />
| 4<br />
| ?<br />
| Writes 0xFF2 on GPU init.<br />
|-<br />
| 0x1EF000C0<br />
| 0x104000C0<br />
| 4<br />
| Backlight control<br />
| Writes 0x0 to allow backlights to turn off, 0x20000000 to force them always on.<br />
|-<br />
| 0x1EF00400<br />
| 0x10400400<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC0" (top screen)<br />
|<br />
|-<br />
| 0x1EF00500<br />
| 0x10400500<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC1" (bottom)<br />
|<br />
|-<br />
| 0x1EF00C00<br />
| 0x10400C00<br />
| ?<br />
| [[#Transfer_Engine|Transfer Engine]] "DMA"<br />
|<br />
|-<br />
|colspan="5"| 0x1EF01000/0x10401000 - 0x1EF01C00/0x10401C00 maps to [[GPU/Internal_Registers|GPU internal registers]]. These registers are usually not read/written directly here, but are written using the command list interface below (corresponding to the GPUREG_CMDBUF_* internal registers)<br />
|-<br />
| 0x1EF01000<br />
| 0x10401000<br />
| 0x4<br />
| ?<br />
| Writes 0 on GPU init and before the Command List is used<br />
|-<br />
| 0x1EF01080<br />
| 0x10401080<br />
| 0x4<br />
| ?<br />
| Writes 0x12345678 on GPU init.<br />
|-<br />
| 0x1EF010C0<br />
| 0x104010C0<br />
| 0x4<br />
| ?<br />
| Writes 0xFFFFFFF0 on GPU init.<br />
|-<br />
| 0x1EF010D0<br />
| 0x104010D0<br />
| 0x4<br />
| ?<br />
| Writes 1 on GPU init.<br />
|-<br />
| 0x1EF014??<br />
| 0x104014??<br />
| 0x14<br />
| "PPF" ?<br />
|<br />
|-<br />
| 0x1EF018E0<br />
| 0x104018E0<br />
| 0x14<br />
| [[#Command_List|Command List]] "P3D"<br />
|<br />
|}<br />
<br />
== Memory Fill ==<br />
{| class="wikitable" border="1"<br />
! User VA<br />
! Description<br />
|-<br />
| 0x1EF000X0<br />
| Buffer start physaddr >> 3<br />
|-<br />
| 0x1EF000X4<br />
| Buffer end physaddr >> 3<br />
|-<br />
| 0x1EF000X8<br />
| Fill value<br />
|-<br />
| 0x1EF000XC<br />
| Control. bit0: start/busy, bit1: finished, bit8-9: fill-width (0=16bit, 1=3=24bit, 2=32bit)<br />
|}<br />
<br />
Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0.<br />
<br />
These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]].<br />
<br />
== LCD Source Framebuffer Setup ==<br />
<br />
All of these registers must be accessed with 32bit operations regardless of the registers' actual bit size.<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Name<br />
! Comments<br />
|-<br />
| 0x00<br />
| H-total (V-total on not physically rotated screens).<br />
| 12bits.<br />
<br />
Setting this value too low will make the screen not be able to sync any pixels other than a single one from the wrong location. The lowest the screen can handle is 0x1C2, at 0x1C1 the display loses a few scanlines worth of pixel clock (though not noticable).<br />
|-<br />
| 0x04<br />
| HBlank timer(?)<br />
| Seems to determine the horizontal blanking interval.<br />
<br />
<br />
Setting this to lower than <code>HTotal - HDisp</code> will make the screen not catch up with the scanlines, some will be skipped, some will be misaligned.<br />
<br />
Setting this to higher than <code>HTotal - HDisp</code> will make the displayed image misaligned to the right.<br />
<br />
Setting this to higher than <code>HTotal</code> seems to make the horizontal synchronization never happen.<br />
|-<br />
| 0x08<br />
| ?<br />
| must be >= REG#0x00<br />
|-<br />
| 0x0C<br />
| ?<br />
| must be >= REG#0x08<br />
|-<br />
| 0x10<br />
| Window X start (LgyFb)<br />
| Offsets the viewing window on the display's physical X co-ordinate relative to its front porch end.<br />
<br />
Outside of LgyFb changing this value only seems to cause weird pixel interpolation and blurryness.<br />
|-<br />
| 0x14<br />
| Window X end (LgyFb)<br />
| Window X start + window width - 1 is written here to set the end display scan pixel offset.<br />
<br />
Outside of LgyFb it seems to offset the screen to the left if this value is high enough, but can glitch out the syncing on the bottom screen. High enough values will make the screen skip too many "pixels". If this value is higher or equal to *some value* (aka. if less than one pixel per line is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x18<br />
| Window Y start (LgyFb)<br />
| Offsets the viewing window on the display's physical Y co-ordinate relative to the first visible scanline.<br />
|-<br />
| 0x20<br />
| Low: Window Y end (LgyFb)<br />
High: ???<br />
| Low: Window Y start + window height - 1 is written here to set the last display scanline relative to the first visible scanline.<br />
<br />
High: This is cleared to zero when displaying LgyFb. Outside of LgyFb this doesn't really seem to do anything useful.<br />
<br />
<br />
??? extra pixels get inserted in the first displayed scanline and thus the image gets shifted to the right. Seems to make horizontal syncing a bit glitchy. If a HSync occurs, the pixel data is suspended until the first pixel is supposed to be displayed, then the pixel stream will continue where it left off until a delayed HSync gets processed relative to the pixel data.<br />
|-<br />
| 0x24<br />
| V-total (H-total on not physically rotated screens).<br />
| Total scanlines including porches/sync timing. Setting this to 494 for the topscreen lowers framerate to about 50.040660858 Hz.<br />
|-<br />
| 0x28<br />
| VBlank timer(?)<br />
| Seems to determine the vertical blanking interval.<br />
<br />
<br />
Setting this to lower than <code>VTotal - VDisp</code> will cut off the top <code>VTotal - VDisp - thisvalue</code> lines.<br />
<br />
Setting this to higher than <code>VTotal - VDisp</code> will make the image be pushed downwards with the overscan color visible.<br />
<br />
Setting this to higher than <code>HTotal</code> will make the GPU skip vertical pixel data synchronization (hence filling the screen with the rest of the pixel data past the given screen framebuffer size). Also will skip <code>thisvalue + somevalue - HTotal</code> lines into the "global" pixel buffer.<br />
|-<br />
| 0x30<br />
| VTotal<br />
| Total amount of vertical scanlines in the pixel buffer, must be bigger than *an unknown blanking-like value*. If this value is less than VDisp then the last two scanlines will be repeated interlaced until VDisp is reached.<br />
|-<br />
| 0x34<br />
| VDisp(?)<br />
| Total amonut of vertical scanlines displayed (only for top screen it seems like). If this value is less than VTotal then the rest of the scanlines will not be updated on the screen, so those will slowly fade out. Must be bigger than *an unknown blanking-like value*, otherwise an underflow will happen.<br />
|-<br />
| 0x38<br />
| Vertical data offset(?)<br />
| ??? Seems to offset the screen upwards if this value is high enough. If this value is higher or equal to *some value* (aka. if less than one scanline is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x44<br />
| ???<br />
| similar functionality to 0x10<br />
|-<br />
| 0x48<br />
| ???<br />
| bit0 seems to disable HSync, bit8 seems to disable VSync, rest of the bits aren't writable.<br />
|-<br />
| 0x4C<br />
| Overscan filler color<br />
| <br />
|-<br />
| 0x50<br />
| Horizontal position counter<br />
| read-only<br />
|-<br />
| 0x54<br />
| Horizontal scanline (HBlank) counter<br />
| read-only<br />
|-<br />
| 0x5C<br />
| ???<br />
| low u16: framebuffer width<br />
high u16: framebuffer height??? (seems to be unused)<br />
|-<br />
| 0x60<br />
| ???<br />
| low u16: timing data(?)<br />
high u16: framebuffer total width (amount of pixels blitted regardless of framebuffer width)<br />
|-<br />
| 0x64<br />
| ???<br />
| low u16: unknown<br />
high u16: framebuffer total height (amount of scanlines blitted regardless of framebuffer height)<br />
|-<br />
| 0x68<br />
| Framebuffer A first address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x6C<br />
| Framebuffer A second address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x70<br />
| Framebuffer format<br />
| Bit0-15: framebuffer format, bit16-31: unknown<br />
|-<br />
| 0x74<br />
| PDC control<br />
| Bit 0: Enable display controller.<br />
Bit 8: H(Blank?) IRQ mask (0 = enabled).<br />
Bit 9: VBlank IRQ mask (0 = enabled).<br />
Bit 10: Error IRQ mask? (0 = enabled).<br />
Bit 16: Output enable?<br />
|-<br />
| 0x78<br />
| Framebuffer select and status<br />
| Bit 0: Next framebuffer to display (after VBlank).<br />
Bit 4: Currently displaying framebuffer?<br />
Bit 8: Reset FIFO?<br />
Bit 16: H(Blank?) IRQ status/ack. Write 1 to aknowledge.<br />
Bit 17: VBlank IRQ status/ack.<br />
Bit 18: Error IRQ status/ack?<br />
|-<br />
| 0x80<br />
| Color lookup table index select<br />
| 8bits, write-only<br />
|-<br />
| 0x84<br />
| Color lookup table indexed element<br />
| Contains the value of the color lookup table indexed by the above register, 24bits, RGB8 (0x00BBGGRR) <br />
Accessing this register will increase the index register by one<br />
|-<br />
| 0x90<br />
| Framebuffer stride<br />
| Distance in bytes between the start of two framebuffer rows (must be a multiple of 8).<br />
|-<br />
| 0x94<br />
| Framebuffer B first address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|-<br />
| 0x98<br />
| Framebuffer B second address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|}<br />
<br />
=== Framebuffer format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Color format<br />
|-<br />
| 3<br />
| ?<br />
|-<br />
| 4<br />
| Unused?<br />
|-<br />
| 5<br />
| Enable parallax barrier (i.e. 3D).<br />
|-<br />
| 6<br />
| 1 = main screen, 0 = sub screen. However if bit5 is set, this bit is cleared.<br />
|-<br />
| 7<br />
| ?<br />
|-<br />
| 9-8<br />
| Value 1 = unknown: get rid of rainbow strip on top of screen, 3 = unknown: black screen.<br />
|-<br />
| 15-10<br />
| Unused?<br />
|}<br />
<br />
GSP module only allows the LCD stereoscopy to be enabled when bit5=1 and bit6=0 here. When GSP module updates this register, GSP module will automatically disable the stereoscopy if those bits are not set for enabling stereoscopy.<br />
<br />
=== Framebuffer color formats ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_RGBA8_OES<br />
|-<br />
| 1<br />
| GL_RGB8_OES<br />
|-<br />
| 2<br />
| GL_RGB565_OES<br />
|-<br />
| 3<br />
| GL_RGB5_A1_OES<br />
|-<br />
| 4<br />
| GL_RGBA4_OES<br />
|}<br />
Color components are laid out in reverse byte order, with the most significant bits used first (i.e. non-24-bit pixels are stored as a little-endian values). For instance, a raw data stream of two GL_RGB565_OES pixels looks like GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG.<br />
<br />
== Transfer Engine ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF00C00<br />
| Input physical address >> 3<br />
|-<br />
| 0x1EF00C04<br />
| Output physical address >> 3<br />
|-<br />
| 0x1EF00C08<br />
| DisplayTransfer output width (bits 0-15) and height (bits 16-31).<br />
|-<br />
| 0x1EF00C0C<br />
| DisplayTransfer input width and height.<br />
|-<br />
| 0x1EF00C10<br />
| Transfer flags. (See below)<br />
|-<br />
| 0x1EF00C14<br />
| GSP module writes value 0 here prior to writing to 0x1EF00C18, for cmd3.<br />
|-<br />
| 0x1EF00C18<br />
| Setting bit0 starts the transfer. Upon completion, bit0 is unset and bit8 is set.<br />
|-<br />
| 0x1EF00C1C<br />
| ?<br />
|-<br />
| 0x1EF00C20<br />
| TextureCopy total amount of data to copy, in bytes.<br />
|-<br />
| 0x1EF00C24<br />
| TextureCopy input line width (bits 0-15) and gap (bits 16-31), in 16 byte units.<br />
|-<br />
| 0x1EF00C28<br />
| TextureCopy output line width and gap.<br />
|}<br />
<br />
These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise.<br />
<br />
==== Flags Register - 0x1EF00C10 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| When set, the framebuffer data is flipped vertically.<br />
|-<br />
| 1<br />
| When set, the input framebuffer is treated as linear and converted to tiled in the output, converts tiled->linear when unset.<br />
|-<br />
| 2<br />
| This bit is required when the output width is less than the input width for the hardware to properly crop the lines, otherwise the output will be mis-aligned.<br />
|-<br />
| 3<br />
| Uses a TextureCopy mode transfer. See below for details.<br />
|-<br />
| 4<br />
| Not writable<br />
|-<br />
| 5<br />
| Don't perform tiled-linear conversion. Incompatible with bit 1, so only tiled-tiled transfers can be done, not linear-linear.<br />
|-<br />
| 7-6<br />
| Not writable<br />
|-<br />
| 10-8<br />
| Input framebuffer color format, value0 and value1 are the same as the [[GPU Registers#Framebuffer_color_formats|LCD Source Framebuffer Formats]] (usually zero)<br />
|-<br />
| 11<br />
| Not writable<br />
|-<br />
| 14-12<br />
| Output framebuffer color format<br />
|-<br />
| 15<br />
| Not writable<br />
|-<br />
| 16<br />
| Use 32x32 block tiling mode, instead of the usual 8x8 one. Output dimensions must be multiples of 32, even if cropping with bit 2 set above.<br />
|-<br />
| 17-23<br />
| Not writable<br />
|-<br />
| 24-25<br />
| Scale down the input image using a box filter. 0 = No downscale, 1 = 2x1 downscale. 2 = 2x2 downscale, 3 = invalid<br />
|-<br />
| 31-26<br />
| Not writable<br />
|}<br />
<br />
=== TextureCopy ===<br />
<br />
When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer. In this mode, all other bits of the control register (except for bit 2, which still needs to be set correctly) and the regular dimension registers are ignored, and no format conversions are done. Instead, it performs a raw data copy from the source to the destination, but with a configurable gap between lines. The total amount of bytes to copy is specified in the size register, and the hardware loops reading lines from the input and writing them to the output until this amount is copied. The "gap" specified in the input/output dimension register is the number of chunks to skip after each "width" chunks of the input/output, and is NOT counted towards the total size of the transfer.<br />
<br />
By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters.<br />
<br />
Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy.<br />
<br />
== Command List ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF018E0<br />
| Buffer size in bytes >> 3<br />
|-<br />
| 0x1EF018E8<br />
| Buffer physical address >> 3<br />
|-<br />
| 0x1EF018F0<br />
| Setting bit0 to 1 enables processing GPU command execution. Upon completion, bit0 seems to be reset to 0.<br />
|}<br />
<br />
These 3 registers are used by [[GSP_Shared_Memory|GX command]] 1. This is used for [[GPU/Internal_Registers|GPU commands]].<br />
<br />
== Framebuffers ==<br />
These LCD framebuffers normally contain the last rendered frames from the GPU. The framebuffers are drawn from left-to-right, instead of top-to-bottom.(Thus the beginning of the framebuffer is drawn starting at the left side of the screen)<br />
<br />
Both of the 3D screen left/right framebuffers are displayed regardless of the 3D slider's state, however when the 3D slider is set to "off" the 3D effect is disabled. Normally when the 3D slider's state is set to "off" the left/right framebuffer addresses are set to the same physical address. When the 3D effect is disabled and the left/right framebuffers are set to separate addresses, the LCD seems to alternate between displaying the left/right framebuffer each frame.<br />
<br />
==== Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00400 = 0x1C2<br />
* 0x1EF00404 = 0xD1<br />
* 0x1EF00408 = 0x1C1<br />
* 0x1EF0040C = 0x1C1<br />
* 0x1EF00410 = 0<br />
* 0x1EF00414 = 0xCF<br />
* 0x1EF00418 = 0xD1<br />
* 0x1EF0041C = 0x1C501C1<br />
* 0x1EF00420 = 0x10000<br />
* 0x1EF00424 = 0x19D<br />
* 0x1EF00428 = 2<br />
* 0x1EF0042C = 0x1C2<br />
* 0x1EF00430 = 0x1C2<br />
* 0x1EF00434 = 0x1C2<br />
* 0x1EF00438 = 1<br />
* 0x1EF0043C = 2<br />
* 0x1EF00440 = 0x1960192<br />
* 0x1EF00444 = 0<br />
* 0x1EF00448 = 0<br />
* 0x1EF0045C = 0x19000F0<br />
* 0x1EF00460 = 0x1c100d1<br />
* 0x1EF00464 = 0x1920002<br />
* 0x1EF00470 = 0x80340<br />
* 0x1EF0049C = 0<br />
<br />
==== More Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00468 = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF0046C = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF00494 = 0x18300000<br />
* 0x1EF00498 = 0x18300000<br />
* 0x1EF00478 = 1, doesn't stay 1, read as 0<br />
* 0x1EF00474 = 0x10501<br />
<br />
[[Category:GPU]]</div>
Profi200
https://www.3dbrew.org/w/index.php?title=GPU/External_Registers&diff=21227
GPU/External Registers
2020-05-07T13:52:20Z
<p>Profi200: /* LCD Source Framebuffer Setup */ Oops.</p>
<hr />
<div>This page describes the address range accessible from the ARM11, used to configure the basic GPU functionality. For information about the internal registers used for 3D rendering, see [[GPU/Internal Registers]].<br />
<br />
== Map ==<br />
Address mappings for the external registers. GSPGPU:WriteHWRegs takes these addresses relative to 0x1EB00000. <br />
{| class="wikitable" border="1"<br />
! User VA<br />
! PA<br />
! Length<br />
! Name<br />
! Comments<br />
|-<br />
| 0x1EF00004<br />
| 0x10400004<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00010<br />
| 0x10400010<br />
| 16<br />
| [[#Memory Fill|Memory Fill1]] "PSC0"<br />
| GX command 2<br />
|-<br />
| 0x1EF00020<br />
| 0x10400020<br />
| 16<br />
| [[#Memory Fill|Memory Fill2]] "PSC1"<br />
| GX command 2<br />
|-<br />
| 0x1EF00030<br />
| 0x10400030<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00034<br />
| 0x10400034<br />
| 4<br />
| GPU Busy<br />
| Bit31 = cmd-list busy, bit27 = PSC0 busy, bit26 = PSC1 busy.<br />
|-<br />
| 0x1EF00050<br />
| 0x10400050<br />
| 4<br />
| ?<br />
| Writes 0x22221200 on GPU init.<br />
|-<br />
| 0x1EF00054<br />
| 0x10400054<br />
| 4<br />
| ?<br />
| Writes 0xFF2 on GPU init.<br />
|-<br />
| 0x1EF000C0<br />
| 0x104000C0<br />
| 4<br />
| Backlight control<br />
| Writes 0x0 to allow backlights to turn off, 0x20000000 to force them always on.<br />
|-<br />
| 0x1EF00400<br />
| 0x10400400<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC0" (top screen)<br />
|<br />
|-<br />
| 0x1EF00500<br />
| 0x10400500<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC1" (bottom)<br />
|<br />
|-<br />
| 0x1EF00C00<br />
| 0x10400C00<br />
| ?<br />
| [[#Transfer_Engine|Transfer Engine]] "DMA"<br />
|<br />
|-<br />
|colspan="5"| 0x1EF01000/0x10401000 - 0x1EF01C00/0x10401C00 maps to [[GPU/Internal_Registers|GPU internal registers]]. These registers are usually not read/written directly here, but are written using the command list interface below (corresponding to the GPUREG_CMDBUF_* internal registers)<br />
|-<br />
| 0x1EF01000<br />
| 0x10401000<br />
| 0x4<br />
| ?<br />
| Writes 0 on GPU init and before the Command List is used<br />
|-<br />
| 0x1EF01080<br />
| 0x10401080<br />
| 0x4<br />
| ?<br />
| Writes 0x12345678 on GPU init.<br />
|-<br />
| 0x1EF010C0<br />
| 0x104010C0<br />
| 0x4<br />
| ?<br />
| Writes 0xFFFFFFF0 on GPU init.<br />
|-<br />
| 0x1EF010D0<br />
| 0x104010D0<br />
| 0x4<br />
| ?<br />
| Writes 1 on GPU init.<br />
|-<br />
| 0x1EF014??<br />
| 0x104014??<br />
| 0x14<br />
| "PPF" ?<br />
|<br />
|-<br />
| 0x1EF018E0<br />
| 0x104018E0<br />
| 0x14<br />
| [[#Command_List|Command List]] "P3D"<br />
|<br />
|}<br />
<br />
== Memory Fill ==<br />
{| class="wikitable" border="1"<br />
! User VA<br />
! Description<br />
|-<br />
| 0x1EF000X0<br />
| Buffer start physaddr >> 3<br />
|-<br />
| 0x1EF000X4<br />
| Buffer end physaddr >> 3<br />
|-<br />
| 0x1EF000X8<br />
| Fill value<br />
|-<br />
| 0x1EF000XC<br />
| Control. bit0: start/busy, bit1: finished, bit8-9: fill-width (0=16bit, 1=3=24bit, 2=32bit)<br />
|}<br />
<br />
Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0.<br />
<br />
These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]].<br />
<br />
== LCD Source Framebuffer Setup ==<br />
<br />
All of these registers must be accessed with 32bit operations regardless of the registers' actual bit size.<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Name<br />
! Comments<br />
|-<br />
| 0x00<br />
| H-total (V-total on not physically rotated screens).<br />
| 12bits.<br />
<br />
Setting this value too low will make the screen not be able to sync any pixels other than a single one from the wrong location. The lowest the screen can handle is 0x1C2, at 0x1C1 the display loses a few scanlines worth of pixel clock (though not noticable).<br />
|-<br />
| 0x04<br />
| HBlank timer(?)<br />
| Seems to determine the horizontal blanking interval.<br />
<br />
<br />
Setting this to lower than <code>HTotal - HDisp</code> will make the screen not catch up with the scanlines, some will be skipped, some will be misaligned.<br />
<br />
Setting this to higher than <code>HTotal - HDisp</code> will make the displayed image misaligned to the right.<br />
<br />
Setting this to higher than <code>HTotal</code> seems to make the horizontal synchronization never happen.<br />
|-<br />
| 0x08<br />
| ?<br />
| must be >= REG#0x00<br />
|-<br />
| 0x0C<br />
| ?<br />
| must be >= REG#0x08<br />
|-<br />
| 0x10<br />
| Window X start (LgyFb)<br />
| Offsets the viewing window on the display's physical X co-ordinate relative to its front porch end.<br />
<br />
Outside of LgyFb changing this value only seems to cause weird pixel interpolation and blurryness.<br />
|-<br />
| 0x14<br />
| Window X end (LgyFb)<br />
| Window X start + window width - 1 is written here to set the end display scan pixel offset.<br />
<br />
Outside of LgyFb it seems to offset the screen to the left if this value is high enough, but can glitch out the syncing on the bottom screen. High enough values will make the screen skip too many "pixels". If this value is higher or equal to *some value* (aka. if less than one pixel per line is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x18<br />
| Window Y start (LgyFb)<br />
| Offsets the viewing window on the display's physical Y co-ordinate relative to the first visible scanline.<br />
|-<br />
| 0x20<br />
| Low: Window Y end (LgyFb)<br />
High: ???<br />
| Low: Window Y start + window height - 1 is written here to set the last display scanline relative to the first visible scanline.<br />
<br />
High: This is cleared to zero when displaying LgyFb. Outside of LgyFb this doesn't really seem to do anything useful.<br />
<br />
<br />
??? extra pixels get inserted in the first displayed scanline and thus the image gets shifted to the right. Seems to make horizontal syncing a bit glitchy. If a HSync occurs, the pixel data is suspended until the first pixel is supposed to be displayed, then the pixel stream will continue where it left off until a delayed HSync gets processed relative to the pixel data.<br />
|-<br />
| 0x24<br />
| V-total (H-total on not physically rotated screens).<br />
| Total scanlines including porches/sync timing. Setting this to 494 lowers framerate to about 50.040660858 Hz.<br />
|-<br />
| 0x28<br />
| VBlank timer(?)<br />
| Seems to determine the vertical blanking interval.<br />
<br />
<br />
Setting this to lower than <code>VTotal - VDisp</code> will cut off the top <code>VTotal - VDisp - thisvalue</code> lines.<br />
<br />
Setting this to higher than <code>VTotal - VDisp</code> will make the image be pushed downwards with the overscan color visible.<br />
<br />
Setting this to higher than <code>HTotal</code> will make the GPU skip vertical pixel data synchronization (hence filling the screen with the rest of the pixel data past the given screen framebuffer size). Also will skip <code>thisvalue + somevalue - HTotal</code> lines into the "global" pixel buffer.<br />
|-<br />
| 0x30<br />
| VTotal<br />
| Total amount of vertical scanlines in the pixel buffer, must be bigger than *an unknown blanking-like value*. If this value is less than VDisp then the last two scanlines will be repeated interlaced until VDisp is reached.<br />
|-<br />
| 0x34<br />
| VDisp(?)<br />
| Total amonut of vertical scanlines displayed (only for top screen it seems like). If this value is less than VTotal then the rest of the scanlines will not be updated on the screen, so those will slowly fade out. Must be bigger than *an unknown blanking-like value*, otherwise an underflow will happen.<br />
|-<br />
| 0x38<br />
| Vertical data offset(?)<br />
| ??? Seems to offset the screen upwards if this value is high enough. If this value is higher or equal to *some value* (aka. if less than one scanline is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x44<br />
| ???<br />
| similar functionality to 0x10<br />
|-<br />
| 0x48<br />
| ???<br />
| bit0 seems to disable HSync, bit8 seems to disable VSync, rest of the bits aren't writable.<br />
|-<br />
| 0x4C<br />
| Overscan filler color<br />
| <br />
|-<br />
| 0x50<br />
| Horizontal position counter<br />
| read-only<br />
|-<br />
| 0x54<br />
| Horizontal scanline (HBlank) counter<br />
| read-only<br />
|-<br />
| 0x5C<br />
| ???<br />
| low u16: framebuffer width<br />
high u16: framebuffer height??? (seems to be unused)<br />
|-<br />
| 0x60<br />
| ???<br />
| low u16: timing data(?)<br />
high u16: framebuffer total width (amount of pixels blitted regardless of framebuffer width)<br />
|-<br />
| 0x64<br />
| ???<br />
| low u16: unknown<br />
high u16: framebuffer total height (amount of scanlines blitted regardless of framebuffer height)<br />
|-<br />
| 0x68<br />
| Framebuffer A first address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x6C<br />
| Framebuffer A second address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x70<br />
| Framebuffer format<br />
| Bit0-15: framebuffer format, bit16-31: unknown<br />
|-<br />
| 0x74<br />
| PDC control<br />
| Bit 0: Enable display controller.<br />
Bit 8: H(Blank?) IRQ mask (0 = enabled).<br />
Bit 9: VBlank IRQ mask (0 = enabled).<br />
Bit 10: Error IRQ mask? (0 = enabled).<br />
Bit 16: Output enable?<br />
|-<br />
| 0x78<br />
| Framebuffer select and status<br />
| Bit 0: Next framebuffer to display (after VBlank).<br />
Bit 4: Currently displaying framebuffer?<br />
Bit 8: Reset FIFO?<br />
Bit 16: H(Blank?) IRQ status/ack. Write 1 to aknowledge.<br />
Bit 17: VBlank IRQ status/ack.<br />
Bit 18: Error IRQ status/ack?<br />
|-<br />
| 0x80<br />
| Color lookup table index select<br />
| 8bits, write-only<br />
|-<br />
| 0x84<br />
| Color lookup table indexed element<br />
| Contains the value of the color lookup table indexed by the above register, 24bits, RGB8 (0x00BBGGRR) <br />
Accessing this register will increase the index register by one<br />
|-<br />
| 0x90<br />
| Framebuffer stride<br />
| Distance in bytes between the start of two framebuffer rows (must be a multiple of 8).<br />
|-<br />
| 0x94<br />
| Framebuffer B first address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|-<br />
| 0x98<br />
| Framebuffer B second address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|}<br />
<br />
=== Framebuffer format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Color format<br />
|-<br />
| 3<br />
| ?<br />
|-<br />
| 4<br />
| Unused?<br />
|-<br />
| 5<br />
| Enable parallax barrier (i.e. 3D).<br />
|-<br />
| 6<br />
| 1 = main screen, 0 = sub screen. However if bit5 is set, this bit is cleared.<br />
|-<br />
| 7<br />
| ?<br />
|-<br />
| 9-8<br />
| Value 1 = unknown: get rid of rainbow strip on top of screen, 3 = unknown: black screen.<br />
|-<br />
| 15-10<br />
| Unused?<br />
|}<br />
<br />
GSP module only allows the LCD stereoscopy to be enabled when bit5=1 and bit6=0 here. When GSP module updates this register, GSP module will automatically disable the stereoscopy if those bits are not set for enabling stereoscopy.<br />
<br />
=== Framebuffer color formats ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_RGBA8_OES<br />
|-<br />
| 1<br />
| GL_RGB8_OES<br />
|-<br />
| 2<br />
| GL_RGB565_OES<br />
|-<br />
| 3<br />
| GL_RGB5_A1_OES<br />
|-<br />
| 4<br />
| GL_RGBA4_OES<br />
|}<br />
Color components are laid out in reverse byte order, with the most significant bits used first (i.e. non-24-bit pixels are stored as a little-endian values). For instance, a raw data stream of two GL_RGB565_OES pixels looks like GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG.<br />
<br />
== Transfer Engine ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF00C00<br />
| Input physical address >> 3<br />
|-<br />
| 0x1EF00C04<br />
| Output physical address >> 3<br />
|-<br />
| 0x1EF00C08<br />
| DisplayTransfer output width (bits 0-15) and height (bits 16-31).<br />
|-<br />
| 0x1EF00C0C<br />
| DisplayTransfer input width and height.<br />
|-<br />
| 0x1EF00C10<br />
| Transfer flags. (See below)<br />
|-<br />
| 0x1EF00C14<br />
| GSP module writes value 0 here prior to writing to 0x1EF00C18, for cmd3.<br />
|-<br />
| 0x1EF00C18<br />
| Setting bit0 starts the transfer. Upon completion, bit0 is unset and bit8 is set.<br />
|-<br />
| 0x1EF00C1C<br />
| ?<br />
|-<br />
| 0x1EF00C20<br />
| TextureCopy total amount of data to copy, in bytes.<br />
|-<br />
| 0x1EF00C24<br />
| TextureCopy input line width (bits 0-15) and gap (bits 16-31), in 16 byte units.<br />
|-<br />
| 0x1EF00C28<br />
| TextureCopy output line width and gap.<br />
|}<br />
<br />
These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise.<br />
<br />
==== Flags Register - 0x1EF00C10 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| When set, the framebuffer data is flipped vertically.<br />
|-<br />
| 1<br />
| When set, the input framebuffer is treated as linear and converted to tiled in the output, converts tiled->linear when unset.<br />
|-<br />
| 2<br />
| This bit is required when the output width is less than the input width for the hardware to properly crop the lines, otherwise the output will be mis-aligned.<br />
|-<br />
| 3<br />
| Uses a TextureCopy mode transfer. See below for details.<br />
|-<br />
| 4<br />
| Not writable<br />
|-<br />
| 5<br />
| Don't perform tiled-linear conversion. Incompatible with bit 1, so only tiled-tiled transfers can be done, not linear-linear.<br />
|-<br />
| 7-6<br />
| Not writable<br />
|-<br />
| 10-8<br />
| Input framebuffer color format, value0 and value1 are the same as the [[GPU Registers#Framebuffer_color_formats|LCD Source Framebuffer Formats]] (usually zero)<br />
|-<br />
| 11<br />
| Not writable<br />
|-<br />
| 14-12<br />
| Output framebuffer color format<br />
|-<br />
| 15<br />
| Not writable<br />
|-<br />
| 16<br />
| Use 32x32 block tiling mode, instead of the usual 8x8 one. Output dimensions must be multiples of 32, even if cropping with bit 2 set above.<br />
|-<br />
| 17-23<br />
| Not writable<br />
|-<br />
| 24-25<br />
| Scale down the input image using a box filter. 0 = No downscale, 1 = 2x1 downscale. 2 = 2x2 downscale, 3 = invalid<br />
|-<br />
| 31-26<br />
| Not writable<br />
|}<br />
<br />
=== TextureCopy ===<br />
<br />
When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer. In this mode, all other bits of the control register (except for bit 2, which still needs to be set correctly) and the regular dimension registers are ignored, and no format conversions are done. Instead, it performs a raw data copy from the source to the destination, but with a configurable gap between lines. The total amount of bytes to copy is specified in the size register, and the hardware loops reading lines from the input and writing them to the output until this amount is copied. The "gap" specified in the input/output dimension register is the number of chunks to skip after each "width" chunks of the input/output, and is NOT counted towards the total size of the transfer.<br />
<br />
By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters.<br />
<br />
Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy.<br />
<br />
== Command List ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF018E0<br />
| Buffer size in bytes >> 3<br />
|-<br />
| 0x1EF018E8<br />
| Buffer physical address >> 3<br />
|-<br />
| 0x1EF018F0<br />
| Setting bit0 to 1 enables processing GPU command execution. Upon completion, bit0 seems to be reset to 0.<br />
|}<br />
<br />
These 3 registers are used by [[GSP_Shared_Memory|GX command]] 1. This is used for [[GPU/Internal_Registers|GPU commands]].<br />
<br />
== Framebuffers ==<br />
These LCD framebuffers normally contain the last rendered frames from the GPU. The framebuffers are drawn from left-to-right, instead of top-to-bottom.(Thus the beginning of the framebuffer is drawn starting at the left side of the screen)<br />
<br />
Both of the 3D screen left/right framebuffers are displayed regardless of the 3D slider's state, however when the 3D slider is set to "off" the 3D effect is disabled. Normally when the 3D slider's state is set to "off" the left/right framebuffer addresses are set to the same physical address. When the 3D effect is disabled and the left/right framebuffers are set to separate addresses, the LCD seems to alternate between displaying the left/right framebuffer each frame.<br />
<br />
==== Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00400 = 0x1C2<br />
* 0x1EF00404 = 0xD1<br />
* 0x1EF00408 = 0x1C1<br />
* 0x1EF0040C = 0x1C1<br />
* 0x1EF00410 = 0<br />
* 0x1EF00414 = 0xCF<br />
* 0x1EF00418 = 0xD1<br />
* 0x1EF0041C = 0x1C501C1<br />
* 0x1EF00420 = 0x10000<br />
* 0x1EF00424 = 0x19D<br />
* 0x1EF00428 = 2<br />
* 0x1EF0042C = 0x1C2<br />
* 0x1EF00430 = 0x1C2<br />
* 0x1EF00434 = 0x1C2<br />
* 0x1EF00438 = 1<br />
* 0x1EF0043C = 2<br />
* 0x1EF00440 = 0x1960192<br />
* 0x1EF00444 = 0<br />
* 0x1EF00448 = 0<br />
* 0x1EF0045C = 0x19000F0<br />
* 0x1EF00460 = 0x1c100d1<br />
* 0x1EF00464 = 0x1920002<br />
* 0x1EF00470 = 0x80340<br />
* 0x1EF0049C = 0<br />
<br />
==== More Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00468 = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF0046C = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF00494 = 0x18300000<br />
* 0x1EF00498 = 0x18300000<br />
* 0x1EF00478 = 1, doesn't stay 1, read as 0<br />
* 0x1EF00474 = 0x10501<br />
<br />
[[Category:GPU]]</div>
Profi200
https://www.3dbrew.org/w/index.php?title=GPU/External_Registers&diff=21226
GPU/External Registers
2020-05-07T13:51:10Z
<p>Profi200: /* LCD Source Framebuffer Setup */ PAL emulator hype.</p>
<hr />
<div>This page describes the address range accessible from the ARM11, used to configure the basic GPU functionality. For information about the internal registers used for 3D rendering, see [[GPU/Internal Registers]].<br />
<br />
== Map ==<br />
Address mappings for the external registers. GSPGPU:WriteHWRegs takes these addresses relative to 0x1EB00000. <br />
{| class="wikitable" border="1"<br />
! User VA<br />
! PA<br />
! Length<br />
! Name<br />
! Comments<br />
|-<br />
| 0x1EF00004<br />
| 0x10400004<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00010<br />
| 0x10400010<br />
| 16<br />
| [[#Memory Fill|Memory Fill1]] "PSC0"<br />
| GX command 2<br />
|-<br />
| 0x1EF00020<br />
| 0x10400020<br />
| 16<br />
| [[#Memory Fill|Memory Fill2]] "PSC1"<br />
| GX command 2<br />
|-<br />
| 0x1EF00030<br />
| 0x10400030<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00034<br />
| 0x10400034<br />
| 4<br />
| GPU Busy<br />
| Bit31 = cmd-list busy, bit27 = PSC0 busy, bit26 = PSC1 busy.<br />
|-<br />
| 0x1EF00050<br />
| 0x10400050<br />
| 4<br />
| ?<br />
| Writes 0x22221200 on GPU init.<br />
|-<br />
| 0x1EF00054<br />
| 0x10400054<br />
| 4<br />
| ?<br />
| Writes 0xFF2 on GPU init.<br />
|-<br />
| 0x1EF000C0<br />
| 0x104000C0<br />
| 4<br />
| Backlight control<br />
| Writes 0x0 to allow backlights to turn off, 0x20000000 to force them always on.<br />
|-<br />
| 0x1EF00400<br />
| 0x10400400<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC0" (top screen)<br />
|<br />
|-<br />
| 0x1EF00500<br />
| 0x10400500<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC1" (bottom)<br />
|<br />
|-<br />
| 0x1EF00C00<br />
| 0x10400C00<br />
| ?<br />
| [[#Transfer_Engine|Transfer Engine]] "DMA"<br />
|<br />
|-<br />
|colspan="5"| 0x1EF01000/0x10401000 - 0x1EF01C00/0x10401C00 maps to [[GPU/Internal_Registers|GPU internal registers]]. These registers are usually not read/written directly here, but are written using the command list interface below (corresponding to the GPUREG_CMDBUF_* internal registers)<br />
|-<br />
| 0x1EF01000<br />
| 0x10401000<br />
| 0x4<br />
| ?<br />
| Writes 0 on GPU init and before the Command List is used<br />
|-<br />
| 0x1EF01080<br />
| 0x10401080<br />
| 0x4<br />
| ?<br />
| Writes 0x12345678 on GPU init.<br />
|-<br />
| 0x1EF010C0<br />
| 0x104010C0<br />
| 0x4<br />
| ?<br />
| Writes 0xFFFFFFF0 on GPU init.<br />
|-<br />
| 0x1EF010D0<br />
| 0x104010D0<br />
| 0x4<br />
| ?<br />
| Writes 1 on GPU init.<br />
|-<br />
| 0x1EF014??<br />
| 0x104014??<br />
| 0x14<br />
| "PPF" ?<br />
|<br />
|-<br />
| 0x1EF018E0<br />
| 0x104018E0<br />
| 0x14<br />
| [[#Command_List|Command List]] "P3D"<br />
|<br />
|}<br />
<br />
== Memory Fill ==<br />
{| class="wikitable" border="1"<br />
! User VA<br />
! Description<br />
|-<br />
| 0x1EF000X0<br />
| Buffer start physaddr >> 3<br />
|-<br />
| 0x1EF000X4<br />
| Buffer end physaddr >> 3<br />
|-<br />
| 0x1EF000X8<br />
| Fill value<br />
|-<br />
| 0x1EF000XC<br />
| Control. bit0: start/busy, bit1: finished, bit8-9: fill-width (0=16bit, 1=3=24bit, 2=32bit)<br />
|}<br />
<br />
Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0.<br />
<br />
These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]].<br />
<br />
== LCD Source Framebuffer Setup ==<br />
<br />
All of these registers must be accessed with 32bit operations regardless of the registers' actual bit size.<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Name<br />
! Comments<br />
|-<br />
| 0x00<br />
| H-total (V-total on not physically rotated screens).<br />
| 12bits.<br />
<br />
Setting this value too low will make the screen not be able to sync any pixels other than a single one from the wrong location. The lowest the screen can handle is 0x1C2, at 0x1C1 the display loses a few scanlines worth of pixel clock (though not noticable).<br />
|-<br />
| 0x04<br />
| HBlank timer(?)<br />
| Seems to determine the horizontal blanking interval.<br />
<br />
<br />
Setting this to lower than <code>HTotal - HDisp</code> will make the screen not catch up with the scanlines, some will be skipped, some will be misaligned.<br />
<br />
Setting this to higher than <code>HTotal - HDisp</code> will make the displayed image misaligned to the right.<br />
<br />
Setting this to higher than <code>HTotal</code> seems to make the horizontal synchronization never happen.<br />
|-<br />
| 0x08<br />
| ?<br />
| must be >= REG#0x00<br />
|-<br />
| 0x0C<br />
| ?<br />
| must be >= REG#0x08<br />
|-<br />
| 0x10<br />
| Window X start (LgyFb)<br />
| Offsets the viewing window on the display's physical X co-ordinate relative to its front porch end.<br />
<br />
Outside of LgyFb changing this value only seems to cause weird pixel interpolation and blurryness.<br />
|-<br />
| 0x14<br />
| Window X end (LgyFb)<br />
| Window X start + window width - 1 is written here to set the end display scan pixel offset.<br />
<br />
Outside of LgyFb it seems to offset the screen to the left if this value is high enough, but can glitch out the syncing on the bottom screen. High enough values will make the screen skip too many "pixels". If this value is higher or equal to *some value* (aka. if less than one pixel per line is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x18<br />
| Window Y start (LgyFb)<br />
| Offsets the viewing window on the display's physical Y co-ordinate relative to the first visible scanline.<br />
|-<br />
| 0x20<br />
| Low: Window Y end (LgyFb)<br />
High: ???<br />
| Low: Window Y start + window height - 1 is written here to set the last display scanline relative to the first visible scanline.<br />
<br />
High: This is cleared to zero when displaying LgyFb. Outside of LgyFb this doesn't really seem to do anything useful.<br />
<br />
<br />
??? extra pixels get inserted in the first displayed scanline and thus the image gets shifted to the right. Seems to make horizontal syncing a bit glitchy. If a HSync occurs, the pixel data is suspended until the first pixel is supposed to be displayed, then the pixel stream will continue where it left off until a delayed HSync gets processed relative to the pixel data.<br />
|-<br />
| 0x24<br />
| V-total (H-total on not physically rotated screens).<br />
| The low 12bit halfword seems to affect:<br />
<br />
Total scanlines including porches/sync timing. Setting this to 494 lowers framerate to about 50.040660858 Hz.<br />
|-<br />
| 0x28<br />
| VBlank timer(?)<br />
| Seems to determine the vertical blanking interval.<br />
<br />
<br />
Setting this to lower than <code>VTotal - VDisp</code> will cut off the top <code>VTotal - VDisp - thisvalue</code> lines.<br />
<br />
Setting this to higher than <code>VTotal - VDisp</code> will make the image be pushed downwards with the overscan color visible.<br />
<br />
Setting this to higher than <code>HTotal</code> will make the GPU skip vertical pixel data synchronization (hence filling the screen with the rest of the pixel data past the given screen framebuffer size). Also will skip <code>thisvalue + somevalue - HTotal</code> lines into the "global" pixel buffer.<br />
|-<br />
| 0x30<br />
| VTotal<br />
| Total amount of vertical scanlines in the pixel buffer, must be bigger than *an unknown blanking-like value*. If this value is less than VDisp then the last two scanlines will be repeated interlaced until VDisp is reached.<br />
|-<br />
| 0x34<br />
| VDisp(?)<br />
| Total amonut of vertical scanlines displayed (only for top screen it seems like). If this value is less than VTotal then the rest of the scanlines will not be updated on the screen, so those will slowly fade out. Must be bigger than *an unknown blanking-like value*, otherwise an underflow will happen.<br />
|-<br />
| 0x38<br />
| Vertical data offset(?)<br />
| ??? Seems to offset the screen upwards if this value is high enough. If this value is higher or equal to *some value* (aka. if less than one scanline is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x44<br />
| ???<br />
| similar functionality to 0x10<br />
|-<br />
| 0x48<br />
| ???<br />
| bit0 seems to disable HSync, bit8 seems to disable VSync, rest of the bits aren't writable.<br />
|-<br />
| 0x4C<br />
| Overscan filler color<br />
| <br />
|-<br />
| 0x50<br />
| Horizontal position counter<br />
| read-only<br />
|-<br />
| 0x54<br />
| Horizontal scanline (HBlank) counter<br />
| read-only<br />
|-<br />
| 0x5C<br />
| ???<br />
| low u16: framebuffer width<br />
high u16: framebuffer height??? (seems to be unused)<br />
|-<br />
| 0x60<br />
| ???<br />
| low u16: timing data(?)<br />
high u16: framebuffer total width (amount of pixels blitted regardless of framebuffer width)<br />
|-<br />
| 0x64<br />
| ???<br />
| low u16: unknown<br />
high u16: framebuffer total height (amount of scanlines blitted regardless of framebuffer height)<br />
|-<br />
| 0x68<br />
| Framebuffer A first address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x6C<br />
| Framebuffer A second address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x70<br />
| Framebuffer format<br />
| Bit0-15: framebuffer format, bit16-31: unknown<br />
|-<br />
| 0x74<br />
| PDC control<br />
| Bit 0: Enable display controller.<br />
Bit 8: H(Blank?) IRQ mask (0 = enabled).<br />
Bit 9: VBlank IRQ mask (0 = enabled).<br />
Bit 10: Error IRQ mask? (0 = enabled).<br />
Bit 16: Output enable?<br />
|-<br />
| 0x78<br />
| Framebuffer select and status<br />
| Bit 0: Next framebuffer to display (after VBlank).<br />
Bit 4: Currently displaying framebuffer?<br />
Bit 8: Reset FIFO?<br />
Bit 16: H(Blank?) IRQ status/ack. Write 1 to aknowledge.<br />
Bit 17: VBlank IRQ status/ack.<br />
Bit 18: Error IRQ status/ack?<br />
|-<br />
| 0x80<br />
| Color lookup table index select<br />
| 8bits, write-only<br />
|-<br />
| 0x84<br />
| Color lookup table indexed element<br />
| Contains the value of the color lookup table indexed by the above register, 24bits, RGB8 (0x00BBGGRR) <br />
Accessing this register will increase the index register by one<br />
|-<br />
| 0x90<br />
| Framebuffer stride<br />
| Distance in bytes between the start of two framebuffer rows (must be a multiple of 8).<br />
|-<br />
| 0x94<br />
| Framebuffer B first address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|-<br />
| 0x98<br />
| Framebuffer B second address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|}<br />
<br />
=== Framebuffer format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Color format<br />
|-<br />
| 3<br />
| ?<br />
|-<br />
| 4<br />
| Unused?<br />
|-<br />
| 5<br />
| Enable parallax barrier (i.e. 3D).<br />
|-<br />
| 6<br />
| 1 = main screen, 0 = sub screen. However if bit5 is set, this bit is cleared.<br />
|-<br />
| 7<br />
| ?<br />
|-<br />
| 9-8<br />
| Value 1 = unknown: get rid of rainbow strip on top of screen, 3 = unknown: black screen.<br />
|-<br />
| 15-10<br />
| Unused?<br />
|}<br />
<br />
GSP module only allows the LCD stereoscopy to be enabled when bit5=1 and bit6=0 here. When GSP module updates this register, GSP module will automatically disable the stereoscopy if those bits are not set for enabling stereoscopy.<br />
<br />
=== Framebuffer color formats ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_RGBA8_OES<br />
|-<br />
| 1<br />
| GL_RGB8_OES<br />
|-<br />
| 2<br />
| GL_RGB565_OES<br />
|-<br />
| 3<br />
| GL_RGB5_A1_OES<br />
|-<br />
| 4<br />
| GL_RGBA4_OES<br />
|}<br />
Color components are laid out in reverse byte order, with the most significant bits used first (i.e. non-24-bit pixels are stored as a little-endian values). For instance, a raw data stream of two GL_RGB565_OES pixels looks like GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG.<br />
<br />
== Transfer Engine ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF00C00<br />
| Input physical address >> 3<br />
|-<br />
| 0x1EF00C04<br />
| Output physical address >> 3<br />
|-<br />
| 0x1EF00C08<br />
| DisplayTransfer output width (bits 0-15) and height (bits 16-31).<br />
|-<br />
| 0x1EF00C0C<br />
| DisplayTransfer input width and height.<br />
|-<br />
| 0x1EF00C10<br />
| Transfer flags. (See below)<br />
|-<br />
| 0x1EF00C14<br />
| GSP module writes value 0 here prior to writing to 0x1EF00C18, for cmd3.<br />
|-<br />
| 0x1EF00C18<br />
| Setting bit0 starts the transfer. Upon completion, bit0 is unset and bit8 is set.<br />
|-<br />
| 0x1EF00C1C<br />
| ?<br />
|-<br />
| 0x1EF00C20<br />
| TextureCopy total amount of data to copy, in bytes.<br />
|-<br />
| 0x1EF00C24<br />
| TextureCopy input line width (bits 0-15) and gap (bits 16-31), in 16 byte units.<br />
|-<br />
| 0x1EF00C28<br />
| TextureCopy output line width and gap.<br />
|}<br />
<br />
These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise.<br />
<br />
==== Flags Register - 0x1EF00C10 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| When set, the framebuffer data is flipped vertically.<br />
|-<br />
| 1<br />
| When set, the input framebuffer is treated as linear and converted to tiled in the output, converts tiled->linear when unset.<br />
|-<br />
| 2<br />
| This bit is required when the output width is less than the input width for the hardware to properly crop the lines, otherwise the output will be mis-aligned.<br />
|-<br />
| 3<br />
| Uses a TextureCopy mode transfer. See below for details.<br />
|-<br />
| 4<br />
| Not writable<br />
|-<br />
| 5<br />
| Don't perform tiled-linear conversion. Incompatible with bit 1, so only tiled-tiled transfers can be done, not linear-linear.<br />
|-<br />
| 7-6<br />
| Not writable<br />
|-<br />
| 10-8<br />
| Input framebuffer color format, value0 and value1 are the same as the [[GPU Registers#Framebuffer_color_formats|LCD Source Framebuffer Formats]] (usually zero)<br />
|-<br />
| 11<br />
| Not writable<br />
|-<br />
| 14-12<br />
| Output framebuffer color format<br />
|-<br />
| 15<br />
| Not writable<br />
|-<br />
| 16<br />
| Use 32x32 block tiling mode, instead of the usual 8x8 one. Output dimensions must be multiples of 32, even if cropping with bit 2 set above.<br />
|-<br />
| 17-23<br />
| Not writable<br />
|-<br />
| 24-25<br />
| Scale down the input image using a box filter. 0 = No downscale, 1 = 2x1 downscale. 2 = 2x2 downscale, 3 = invalid<br />
|-<br />
| 31-26<br />
| Not writable<br />
|}<br />
<br />
=== TextureCopy ===<br />
<br />
When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer. In this mode, all other bits of the control register (except for bit 2, which still needs to be set correctly) and the regular dimension registers are ignored, and no format conversions are done. Instead, it performs a raw data copy from the source to the destination, but with a configurable gap between lines. The total amount of bytes to copy is specified in the size register, and the hardware loops reading lines from the input and writing them to the output until this amount is copied. The "gap" specified in the input/output dimension register is the number of chunks to skip after each "width" chunks of the input/output, and is NOT counted towards the total size of the transfer.<br />
<br />
By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters.<br />
<br />
Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy.<br />
<br />
== Command List ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF018E0<br />
| Buffer size in bytes >> 3<br />
|-<br />
| 0x1EF018E8<br />
| Buffer physical address >> 3<br />
|-<br />
| 0x1EF018F0<br />
| Setting bit0 to 1 enables processing GPU command execution. Upon completion, bit0 seems to be reset to 0.<br />
|}<br />
<br />
These 3 registers are used by [[GSP_Shared_Memory|GX command]] 1. This is used for [[GPU/Internal_Registers|GPU commands]].<br />
<br />
== Framebuffers ==<br />
These LCD framebuffers normally contain the last rendered frames from the GPU. The framebuffers are drawn from left-to-right, instead of top-to-bottom.(Thus the beginning of the framebuffer is drawn starting at the left side of the screen)<br />
<br />
Both of the 3D screen left/right framebuffers are displayed regardless of the 3D slider's state, however when the 3D slider is set to "off" the 3D effect is disabled. Normally when the 3D slider's state is set to "off" the left/right framebuffer addresses are set to the same physical address. When the 3D effect is disabled and the left/right framebuffers are set to separate addresses, the LCD seems to alternate between displaying the left/right framebuffer each frame.<br />
<br />
==== Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00400 = 0x1C2<br />
* 0x1EF00404 = 0xD1<br />
* 0x1EF00408 = 0x1C1<br />
* 0x1EF0040C = 0x1C1<br />
* 0x1EF00410 = 0<br />
* 0x1EF00414 = 0xCF<br />
* 0x1EF00418 = 0xD1<br />
* 0x1EF0041C = 0x1C501C1<br />
* 0x1EF00420 = 0x10000<br />
* 0x1EF00424 = 0x19D<br />
* 0x1EF00428 = 2<br />
* 0x1EF0042C = 0x1C2<br />
* 0x1EF00430 = 0x1C2<br />
* 0x1EF00434 = 0x1C2<br />
* 0x1EF00438 = 1<br />
* 0x1EF0043C = 2<br />
* 0x1EF00440 = 0x1960192<br />
* 0x1EF00444 = 0<br />
* 0x1EF00448 = 0<br />
* 0x1EF0045C = 0x19000F0<br />
* 0x1EF00460 = 0x1c100d1<br />
* 0x1EF00464 = 0x1920002<br />
* 0x1EF00470 = 0x80340<br />
* 0x1EF0049C = 0<br />
<br />
==== More Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00468 = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF0046C = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF00494 = 0x18300000<br />
* 0x1EF00498 = 0x18300000<br />
* 0x1EF00478 = 1, doesn't stay 1, read as 0<br />
* 0x1EF00474 = 0x10501<br />
<br />
[[Category:GPU]]</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21225
CONFIG11 Registers
2020-05-07T13:39:07Z
<p>Profi200: /* LGY_PADCNT */ Broken link.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_FCRAM_CNT followed by 1 and waiting for bit 3 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
Also named "KEYCNT" on certain other DS(i)/GBA documentations.<br />
The value of this register is copied to [[HID_Registers|HID_PADCNT]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=GPU/External_Registers&diff=21224
GPU/External Registers
2020-05-07T13:35:50Z
<p>Profi200: /* LCD Source Framebuffer Setup */</p>
<hr />
<div>This page describes the address range accessible from the ARM11, used to configure the basic GPU functionality. For information about the internal registers used for 3D rendering, see [[GPU/Internal Registers]].<br />
<br />
== Map ==<br />
Address mappings for the external registers. GSPGPU:WriteHWRegs takes these addresses relative to 0x1EB00000. <br />
{| class="wikitable" border="1"<br />
! User VA<br />
! PA<br />
! Length<br />
! Name<br />
! Comments<br />
|-<br />
| 0x1EF00004<br />
| 0x10400004<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00010<br />
| 0x10400010<br />
| 16<br />
| [[#Memory Fill|Memory Fill1]] "PSC0"<br />
| GX command 2<br />
|-<br />
| 0x1EF00020<br />
| 0x10400020<br />
| 16<br />
| [[#Memory Fill|Memory Fill2]] "PSC1"<br />
| GX command 2<br />
|-<br />
| 0x1EF00030<br />
| 0x10400030<br />
| 4<br />
| ?<br />
|<br />
|-<br />
| 0x1EF00034<br />
| 0x10400034<br />
| 4<br />
| GPU Busy<br />
| Bit31 = cmd-list busy, bit27 = PSC0 busy, bit26 = PSC1 busy.<br />
|-<br />
| 0x1EF00050<br />
| 0x10400050<br />
| 4<br />
| ?<br />
| Writes 0x22221200 on GPU init.<br />
|-<br />
| 0x1EF00054<br />
| 0x10400054<br />
| 4<br />
| ?<br />
| Writes 0xFF2 on GPU init.<br />
|-<br />
| 0x1EF000C0<br />
| 0x104000C0<br />
| 4<br />
| Backlight control<br />
| Writes 0x0 to allow backlights to turn off, 0x20000000 to force them always on.<br />
|-<br />
| 0x1EF00400<br />
| 0x10400400<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC0" (top screen)<br />
|<br />
|-<br />
| 0x1EF00500<br />
| 0x10400500<br />
| 0x100<br />
| [[#LCD Source Framebuffer Setup|Framebuffer Setup]] "PDC1" (bottom)<br />
|<br />
|-<br />
| 0x1EF00C00<br />
| 0x10400C00<br />
| ?<br />
| [[#Transfer_Engine|Transfer Engine]] "DMA"<br />
|<br />
|-<br />
|colspan="5"| 0x1EF01000/0x10401000 - 0x1EF01C00/0x10401C00 maps to [[GPU/Internal_Registers|GPU internal registers]]. These registers are usually not read/written directly here, but are written using the command list interface below (corresponding to the GPUREG_CMDBUF_* internal registers)<br />
|-<br />
| 0x1EF01000<br />
| 0x10401000<br />
| 0x4<br />
| ?<br />
| Writes 0 on GPU init and before the Command List is used<br />
|-<br />
| 0x1EF01080<br />
| 0x10401080<br />
| 0x4<br />
| ?<br />
| Writes 0x12345678 on GPU init.<br />
|-<br />
| 0x1EF010C0<br />
| 0x104010C0<br />
| 0x4<br />
| ?<br />
| Writes 0xFFFFFFF0 on GPU init.<br />
|-<br />
| 0x1EF010D0<br />
| 0x104010D0<br />
| 0x4<br />
| ?<br />
| Writes 1 on GPU init.<br />
|-<br />
| 0x1EF014??<br />
| 0x104014??<br />
| 0x14<br />
| "PPF" ?<br />
|<br />
|-<br />
| 0x1EF018E0<br />
| 0x104018E0<br />
| 0x14<br />
| [[#Command_List|Command List]] "P3D"<br />
|<br />
|}<br />
<br />
== Memory Fill ==<br />
{| class="wikitable" border="1"<br />
! User VA<br />
! Description<br />
|-<br />
| 0x1EF000X0<br />
| Buffer start physaddr >> 3<br />
|-<br />
| 0x1EF000X4<br />
| Buffer end physaddr >> 3<br />
|-<br />
| 0x1EF000X8<br />
| Fill value<br />
|-<br />
| 0x1EF000XC<br />
| Control. bit0: start/busy, bit1: finished, bit8-9: fill-width (0=16bit, 1=3=24bit, 2=32bit)<br />
|}<br />
<br />
Memory fills are used to initialize buffers in memory with a given value, similar to memset. A memory fill is triggered by setting bit0 in the control register. Doing so aborts any running memory fills on that filling unit. Upon completion, the hardware unsets bit0 and sets bit1 and fires interrupt PSC0.<br />
<br />
These registers are used by [[GSP Shared Memory#GX SetMemoryFill|GX SetMemoryFill]].<br />
<br />
== LCD Source Framebuffer Setup ==<br />
<br />
All of these registers must be accessed with 32bit operations regardless of the registers' actual bit size.<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Name<br />
! Comments<br />
|-<br />
| 0x00<br />
| Pixel clock<br />
| Higher values are slower, 12bits.<br />
<br />
Setting this value too low will make the screen not be able to sync any pixels other than a single one from the wrong location. The lowest the screen can handle is 0x1C2, at 0x1C1 the display loses a few scanlines worth of pixel clock (though not noticable).<br />
|-<br />
| 0x04<br />
| HBlank timer(?)<br />
| Seems to determine the horizontal blanking interval.<br />
<br />
<br />
Setting this to lower than <code>HTotal - HDisp</code> will make the screen not catch up with the scanlines, some will be skipped, some will be misaligned.<br />
<br />
Setting this to higher than <code>HTotal - HDisp</code> will make the displayed image misaligned to the right.<br />
<br />
Setting this to higher than <code>HTotal</code> seems to make the horizontal synchronization never happen.<br />
|-<br />
| 0x08<br />
| ?<br />
| must be >= REG#0x00<br />
|-<br />
| 0x0C<br />
| ?<br />
| must be >= REG#0x08<br />
|-<br />
| 0x10<br />
| Window X start (LgyFb)<br />
| Offsets the viewing window on the display's physical X co-ordinate relative to its front porch end.<br />
<br />
Outside of LgyFb changing this value only seems to cause weird pixel interpolation and blurryness.<br />
|-<br />
| 0x14<br />
| Window X end (LgyFb)<br />
| Window X start + window width - 1 is written here to set the end display scan pixel offset.<br />
<br />
Outside of LgyFb it seems to offset the screen to the left if this value is high enough, but can glitch out the syncing on the bottom screen. High enough values will make the screen skip too many "pixels". If this value is higher or equal to *some value* (aka. if less than one pixel per line is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x18<br />
| Window Y start (LgyFb)<br />
| Offsets the viewing window on the display's physical Y co-ordinate relative to the first visible scanline.<br />
|-<br />
| 0x20<br />
| Low: Window Y end (LgyFb)<br />
High: ???<br />
| Low: Window Y start + window height - 1 is written here to set the last display scanline relative to the first visible scanline.<br />
<br />
High: This is cleared to zero when displaying LgyFb. Outside of LgyFb this doesn't really seem to do anything useful.<br />
<br />
<br />
??? extra pixels get inserted in the first displayed scanline and thus the image gets shifted to the right. Seems to make horizontal syncing a bit glitchy. If a HSync occurs, the pixel data is suspended until the first pixel is supposed to be displayed, then the pixel stream will continue where it left off until a delayed HSync gets processed relative to the pixel data.<br />
|-<br />
| 0x24<br />
| Low: ???<br />
High: ???<br />
| The low 12bit halfword seems to affect:<br />
<br />
- the total amount of scanlines displayed<br />
<br />
- vertical pixel data offset if the GPU can't VSync properly<br />
<br />
- VSync length<br />
|-<br />
| 0x28<br />
| VBlank timer(?)<br />
| Seems to determine the vertical blanking interval.<br />
<br />
<br />
Setting this to lower than <code>VTotal - VDisp</code> will cut off the top <code>VTotal - VDisp - thisvalue</code> lines.<br />
<br />
Setting this to higher than <code>VTotal - VDisp</code> will make the image be pushed downwards with the overscan color visible.<br />
<br />
Setting this to higher than <code>HTotal</code> will make the GPU skip vertical pixel data synchronization (hence filling the screen with the rest of the pixel data past the given screen framebuffer size). Also will skip <code>thisvalue + somevalue - HTotal</code> lines into the "global" pixel buffer.<br />
|-<br />
| 0x30<br />
| VTotal<br />
| Total amount of vertical scanlines in the pixel buffer, must be bigger than *an unknown blanking-like value*. If this value is less than VDisp then the last two scanlines will be repeated interlaced until VDisp is reached.<br />
|-<br />
| 0x34<br />
| VDisp(?)<br />
| Total amonut of vertical scanlines displayed (only for top screen it seems like). If this value is less than VTotal then the rest of the scanlines will not be updated on the screen, so those will slowly fade out. Must be bigger than *an unknown blanking-like value*, otherwise an underflow will happen.<br />
|-<br />
| 0x38<br />
| Vertical data offset(?)<br />
| ??? Seems to offset the screen upwards if this value is high enough. If this value is higher or equal to *some value* (aka. if less than one scanline is displayed on the screen) then the screen will lose synchronization.<br />
|-<br />
| 0x44<br />
| ???<br />
| similar functionality to 0x10<br />
|-<br />
| 0x48<br />
| ???<br />
| bit0 seems to disable HSync, bit8 seems to disable VSync, rest of the bits aren't writable.<br />
|-<br />
| 0x4C<br />
| Overscan filler color<br />
| <br />
|-<br />
| 0x50<br />
| Horizontal position counter<br />
| read-only<br />
|-<br />
| 0x54<br />
| Horizontal scanline (HBlank) counter<br />
| read-only<br />
|-<br />
| 0x5C<br />
| ???<br />
| low u16: framebuffer width<br />
high u16: framebuffer height??? (seems to be unused)<br />
|-<br />
| 0x60<br />
| ???<br />
| low u16: timing data(?)<br />
high u16: framebuffer total width (amount of pixels blitted regardless of framebuffer width)<br />
|-<br />
| 0x64<br />
| ???<br />
| low u16: unknown<br />
high u16: framebuffer total height (amount of scanlines blitted regardless of framebuffer height)<br />
|-<br />
| 0x68<br />
| Framebuffer A first address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x6C<br />
| Framebuffer A second address<br />
| For top screen, this is the left eye 3D framebuffer.<br />
|-<br />
| 0x70<br />
| Framebuffer format<br />
| Bit0-15: framebuffer format, bit16-31: unknown<br />
|-<br />
| 0x74<br />
| PDC control<br />
| Bit 0: Enable display controller.<br />
Bit 8: H(Blank?) IRQ mask (0 = enabled).<br />
Bit 9: VBlank IRQ mask (0 = enabled).<br />
Bit 10: Error IRQ mask? (0 = enabled).<br />
Bit 16: Output enable?<br />
|-<br />
| 0x78<br />
| Framebuffer select and status<br />
| Bit 0: Next framebuffer to display (after VBlank).<br />
Bit 4: Currently displaying framebuffer?<br />
Bit 8: Reset FIFO?<br />
Bit 16: H(Blank?) IRQ status/ack. Write 1 to aknowledge.<br />
Bit 17: VBlank IRQ status/ack.<br />
Bit 18: Error IRQ status/ack?<br />
|-<br />
| 0x80<br />
| Color lookup table index select<br />
| 8bits, write-only<br />
|-<br />
| 0x84<br />
| Color lookup table indexed element<br />
| Contains the value of the color lookup table indexed by the above register, 24bits, RGB8 (0x00BBGGRR) <br />
Accessing this register will increase the index register by one<br />
|-<br />
| 0x90<br />
| Framebuffer stride<br />
| Distance in bytes between the start of two framebuffer rows (must be a multiple of 8).<br />
|-<br />
| 0x94<br />
| Framebuffer B first address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|-<br />
| 0x98<br />
| Framebuffer B second address<br />
| For top screen, this is the right eye 3D framebuffer. Unused for bottom screen.<br />
|}<br />
<br />
=== Framebuffer format ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Bit<br />
! Description<br />
|-<br />
| 2-0<br />
| Color format<br />
|-<br />
| 3<br />
| ?<br />
|-<br />
| 4<br />
| Unused?<br />
|-<br />
| 5<br />
| Enable parallax barrier (i.e. 3D).<br />
|-<br />
| 6<br />
| 1 = main screen, 0 = sub screen. However if bit5 is set, this bit is cleared.<br />
|-<br />
| 7<br />
| ?<br />
|-<br />
| 9-8<br />
| Value 1 = unknown: get rid of rainbow strip on top of screen, 3 = unknown: black screen.<br />
|-<br />
| 15-10<br />
| Unused?<br />
|}<br />
<br />
GSP module only allows the LCD stereoscopy to be enabled when bit5=1 and bit6=0 here. When GSP module updates this register, GSP module will automatically disable the stereoscopy if those bits are not set for enabling stereoscopy.<br />
<br />
=== Framebuffer color formats ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| GL_RGBA8_OES<br />
|-<br />
| 1<br />
| GL_RGB8_OES<br />
|-<br />
| 2<br />
| GL_RGB565_OES<br />
|-<br />
| 3<br />
| GL_RGB5_A1_OES<br />
|-<br />
| 4<br />
| GL_RGBA4_OES<br />
|}<br />
Color components are laid out in reverse byte order, with the most significant bits used first (i.e. non-24-bit pixels are stored as a little-endian values). For instance, a raw data stream of two GL_RGB565_OES pixels looks like GGGBBBBB RRRRRGGG GGGBBBBB RRRRRGGG.<br />
<br />
== Transfer Engine ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF00C00<br />
| Input physical address >> 3<br />
|-<br />
| 0x1EF00C04<br />
| Output physical address >> 3<br />
|-<br />
| 0x1EF00C08<br />
| DisplayTransfer output width (bits 0-15) and height (bits 16-31).<br />
|-<br />
| 0x1EF00C0C<br />
| DisplayTransfer input width and height.<br />
|-<br />
| 0x1EF00C10<br />
| Transfer flags. (See below)<br />
|-<br />
| 0x1EF00C14<br />
| GSP module writes value 0 here prior to writing to 0x1EF00C18, for cmd3.<br />
|-<br />
| 0x1EF00C18<br />
| Setting bit0 starts the transfer. Upon completion, bit0 is unset and bit8 is set.<br />
|-<br />
| 0x1EF00C1C<br />
| ?<br />
|-<br />
| 0x1EF00C20<br />
| TextureCopy total amount of data to copy, in bytes.<br />
|-<br />
| 0x1EF00C24<br />
| TextureCopy input line width (bits 0-15) and gap (bits 16-31), in 16 byte units.<br />
|-<br />
| 0x1EF00C28<br />
| TextureCopy output line width and gap.<br />
|}<br />
<br />
These registers are used by [[GSP_Shared_Memory|GX command]] 3 and 4. For cmd4, *0x1EF00C18 |= 1 is used instead of just writing value 1. The DisplayTransfer registers are only used if bit 3 of the flags is unset and ignored otherwise. The TextureCopy registers are likewise only used if bit 3 is set, and ignored otherwise.<br />
<br />
==== Flags Register - 0x1EF00C10 ====<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| When set, the framebuffer data is flipped vertically.<br />
|-<br />
| 1<br />
| When set, the input framebuffer is treated as linear and converted to tiled in the output, converts tiled->linear when unset.<br />
|-<br />
| 2<br />
| This bit is required when the output width is less than the input width for the hardware to properly crop the lines, otherwise the output will be mis-aligned.<br />
|-<br />
| 3<br />
| Uses a TextureCopy mode transfer. See below for details.<br />
|-<br />
| 4<br />
| Not writable<br />
|-<br />
| 5<br />
| Don't perform tiled-linear conversion. Incompatible with bit 1, so only tiled-tiled transfers can be done, not linear-linear.<br />
|-<br />
| 7-6<br />
| Not writable<br />
|-<br />
| 10-8<br />
| Input framebuffer color format, value0 and value1 are the same as the [[GPU Registers#Framebuffer_color_formats|LCD Source Framebuffer Formats]] (usually zero)<br />
|-<br />
| 11<br />
| Not writable<br />
|-<br />
| 14-12<br />
| Output framebuffer color format<br />
|-<br />
| 15<br />
| Not writable<br />
|-<br />
| 16<br />
| Use 32x32 block tiling mode, instead of the usual 8x8 one. Output dimensions must be multiples of 32, even if cropping with bit 2 set above.<br />
|-<br />
| 17-23<br />
| Not writable<br />
|-<br />
| 24-25<br />
| Scale down the input image using a box filter. 0 = No downscale, 1 = 2x1 downscale. 2 = 2x2 downscale, 3 = invalid<br />
|-<br />
| 31-26<br />
| Not writable<br />
|}<br />
<br />
=== TextureCopy ===<br />
<br />
When bit 3 of the control register is set, the hardware performs a TextureCopy-mode transfer. In this mode, all other bits of the control register (except for bit 2, which still needs to be set correctly) and the regular dimension registers are ignored, and no format conversions are done. Instead, it performs a raw data copy from the source to the destination, but with a configurable gap between lines. The total amount of bytes to copy is specified in the size register, and the hardware loops reading lines from the input and writing them to the output until this amount is copied. The "gap" specified in the input/output dimension register is the number of chunks to skip after each "width" chunks of the input/output, and is NOT counted towards the total size of the transfer.<br />
<br />
By correctly calculating the input and output gap sizes it is possible to use this functionality to copy arbitrary sub-rectangles between differently-sized framebuffers or textures, which is one of its main uses over a regular no-conversion DisplayTransfer. When copying tiled textures/framebuffers it's important to remember that the contents of a tile are laid out sequentially in memory, and so this should be taken into account when calculating the transfer parameters.<br />
<br />
Specifying invalid/junk values for the TextureCopy dimensions can result in the GPU hanging while attempting to process this TextureCopy.<br />
<br />
== Command List ==<br />
{| class="wikitable" border="1"<br />
! Register address<br />
! Description<br />
|-<br />
| 0x1EF018E0<br />
| Buffer size in bytes >> 3<br />
|-<br />
| 0x1EF018E8<br />
| Buffer physical address >> 3<br />
|-<br />
| 0x1EF018F0<br />
| Setting bit0 to 1 enables processing GPU command execution. Upon completion, bit0 seems to be reset to 0.<br />
|}<br />
<br />
These 3 registers are used by [[GSP_Shared_Memory|GX command]] 1. This is used for [[GPU/Internal_Registers|GPU commands]].<br />
<br />
== Framebuffers ==<br />
These LCD framebuffers normally contain the last rendered frames from the GPU. The framebuffers are drawn from left-to-right, instead of top-to-bottom.(Thus the beginning of the framebuffer is drawn starting at the left side of the screen)<br />
<br />
Both of the 3D screen left/right framebuffers are displayed regardless of the 3D slider's state, however when the 3D slider is set to "off" the 3D effect is disabled. Normally when the 3D slider's state is set to "off" the left/right framebuffer addresses are set to the same physical address. When the 3D effect is disabled and the left/right framebuffers are set to separate addresses, the LCD seems to alternate between displaying the left/right framebuffer each frame.<br />
<br />
==== Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00400 = 0x1C2<br />
* 0x1EF00404 = 0xD1<br />
* 0x1EF00408 = 0x1C1<br />
* 0x1EF0040C = 0x1C1<br />
* 0x1EF00410 = 0<br />
* 0x1EF00414 = 0xCF<br />
* 0x1EF00418 = 0xD1<br />
* 0x1EF0041C = 0x1C501C1<br />
* 0x1EF00420 = 0x10000<br />
* 0x1EF00424 = 0x19D<br />
* 0x1EF00428 = 2<br />
* 0x1EF0042C = 0x1C2<br />
* 0x1EF00430 = 0x1C2<br />
* 0x1EF00434 = 0x1C2<br />
* 0x1EF00438 = 1<br />
* 0x1EF0043C = 2<br />
* 0x1EF00440 = 0x1960192<br />
* 0x1EF00444 = 0<br />
* 0x1EF00448 = 0<br />
* 0x1EF0045C = 0x19000F0<br />
* 0x1EF00460 = 0x1c100d1<br />
* 0x1EF00464 = 0x1920002<br />
* 0x1EF00470 = 0x80340<br />
* 0x1EF0049C = 0<br />
<br />
==== More Init Values from nngxInitialize for Top Screen ====<br />
* 0x1EF00468 = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF0046C = 0x18300000, later changed by GSP module when updating state, framebuffer<br />
* 0x1EF00494 = 0x18300000<br />
* 0x1EF00498 = 0x18300000<br />
* 0x1EF00478 = 1, doesn't stay 1, read as 0<br />
* 0x1EF00474 = 0x10501<br />
<br />
[[Category:GPU]]</div>
Profi200
https://www.3dbrew.org/w/index.php?title=HID_Registers&diff=21169
HID Registers
2020-04-25T14:34:55Z
<p>Profi200: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#HID_PAD|HID_PAD]]<br />
| 0x10146000<br />
| 2<br />
| Boot9, Boot11, Kernel11, TwlBg, HID Services, dlp Services<br />
|-<br />
| style="background: green" | Yes<br />
| [[#HID_PADCNT|HID_PADCNT]]<br />
| 0x10146002<br />
| 2<br />
| TwlBg<br />
|}<br />
<br />
==HID_PAD==<br />
Each bit in this register refers to a particular key. Each bit is set if the corresponding key is '''not''' pressed, and unset if it's pressed.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Key<br />
|-<br />
| 0<br />
| A<br />
|-<br />
| 1<br />
| B<br />
|-<br />
| 2<br />
| Select<br />
|-<br />
| 3<br />
| Start<br />
|-<br />
| 4<br />
| Right<br />
|-<br />
| 5<br />
| Left<br />
|-<br />
| 6<br />
| Up<br />
|-<br />
| 7<br />
| Down<br />
|-<br />
| 8<br />
| R<br />
|-<br />
| 9<br />
| L<br />
|-<br />
| 10<br />
| X<br />
|-<br />
| 11<br />
| Y<br />
|}<br />
<br />
==HID_PADCNT==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Key<br />
|-<br />
| 0<br />
| A<br />
|-<br />
| 1<br />
| B<br />
|-<br />
| 2<br />
| Select<br />
|-<br />
| 3<br />
| Start<br />
|-<br />
| 4<br />
| Right<br />
|-<br />
| 5<br />
| Left<br />
|-<br />
| 6<br />
| Up<br />
|-<br />
| 7<br />
| Down<br />
|-<br />
| 8<br />
| R<br />
|-<br />
| 9<br />
| L<br />
|-<br />
| 10<br />
| X<br />
|-<br />
| 11<br />
| Y<br />
|-<br />
| 12-13<br />
| Unused.<br />
|-<br />
| 14<br />
| Enable IRQ 0x5B. 1 = enable.<br />
|-<br />
| 15<br />
| IRQ condition (0 = OR, 1 = AND).<br />
|}<br />
This is the same as on GBA/DS(i).</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21168
CONFIG11 Registers
2020-04-25T14:20:42Z
<p>Profi200: /* LGY_PADCNT */ Come on.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_FCRAM_CNT followed by 1 and waiting for bit 3 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
Also named "KEYCNT" on certain other DS(i)/GBA documentations.<br />
The value of this register is copied to [[HID_Registers|HID_?]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21167
CONFIG11 Registers
2020-04-25T14:19:22Z
<p>Profi200: /* LGY_MODE */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_FCRAM_CNT followed by 1 and waiting for bit 3 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
Also named "KEYCNT" on certain other DS(i)/GBA documentaions.<br />
The value of this register is copied to [[HID_Registers|HID_?]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21166
CONFIG11 Registers
2020-04-25T14:18:36Z
<p>Profi200: /* LGY_PADCNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_GPU_FCRAM_CNT followed by 1 and waiting for bit 3 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
Also named "KEYCNT" on certain other DS(i)/GBA documentaions.<br />
The value of this register is copied to [[HID_Registers|HID_?]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=21165
CONFIG11 Registers
2020-04-25T14:14:51Z
<p>Profi200: Some juicy legacy mode details.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#LGY_MODE|LGY_MODE]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_SLEEP|LGY_SLEEP]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_IRQ_?|LGY_IRQ_?]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#LGY_PADCNT|LGY_PADCNT]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]]<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]]<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160800.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142800.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143800.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==LGY_MODE==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Read only legacy mode set on reg 0x10018000.<br />
|-<br />
| 2-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = enable legacy mode.<br />
|}<br />
To boot into DSi or GBA mode first set register 0x10018000 to the desired mode and setup LgyFb. Then disable FCRAM by clearing bit 0 in reg 0x10201000, writing 0 to CFG11_GPU_FCRAM_CNT followed by 1 and waiting for bit 3 to clear.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
==LGY_SLEEP==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Write 1 to wakeup GBA mode.<br />
|-<br />
| 1<br />
| Sleep state/ack. 1 when GBA mode entered sleep. Write 1 to ack.<br />
|-<br />
| 2<br />
| ?<br />
|-<br />
| 3-14<br />
| Unused.<br />
|-<br />
| 15<br />
| 1 = IRQ enable (IRQ 0x59)<br />
|}<br />
When a GBA game enters sleep mode and bit 15 is 1, IRQ 0x59 fires and bit 1 is set. Bit 1 must be acknowledged/written together with bit 0 otherwise GBA mode wakes up from sleep early sometimes.<br />
<br />
==LGY_IRQ_?==<br />
Bitfield.<br />
<br />
==LGY_PADCNT==<br />
The value of this register is copied to [[HID_Registers|HID_?]] when GBA mode enters sleep.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_TWLAGB_HIDEMU_MASK==<br />
Set bits will use the corresponding values from [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] instead of allowing the hardware to read it from [[HID_Registers#HID_PAD|HID_PAD]].<br />
<br />
This is set to 0x1FFF (all buttons and the debug key) and [[#CFG11_TWLAGB_HIDEMU_PAD|CFG11_TWLAGB_HIDEMU_PAD]] is set to 0 when the "Close this software and return to HOME Menu?" dialog is shown to prevent the button presses from propagating to the DS/GBA CPU.<br />
<br />
==CFG11_TWLAGB_HIDEMU_PAD==<br />
Works the same way as [[HID_Registers#HID_PAD|HID_PAD]], but the values set here are only replaced in the HID_PAD seen by the DS/GBA CPU when the corresponding bits in [[#CFG11_TWLAGB_HIDEMU_MASK|CFG11_TWLAGB_HIDEMU_MASK]] are set.<br />
<br />
==CFG11_GPU_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Unknown reset. 0 = reset.<br />
|-<br />
| 1<br />
| PSC block reset? 0 = reset.<br />
|-<br />
| 2<br />
| Geoshader block reset? 0 = reset.<br />
|-<br />
| 3<br />
| Rasterization block reset? 0 = reset.<br />
|-<br />
| 4<br />
| PPF block reset. 0 = reset.<br />
|-<br />
| 5<br />
| PDC block reset? 0 = reset.<br />
|-<br />
| 6<br />
| PDC related reset. 0 = reset.<br />
|-<br />
| 7-15<br />
| Unused.<br />
|-<br />
| 16<br />
| Clock enable for all blocks. 1 = enable.<br />
|}<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
PDN uses a 12 ARM11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_FCRAM_CNT==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Reset. 0 = reset.<br />
|-<br />
| 1<br />
| Enable something. 1 = enable.<br />
|-<br />
| 2<br />
| Acknowledge? Gets set or unset when toggling bit 1.<br />
|}<br />
Twl-/AgbBg use this to disable FCRAM for the GBA rom in GBA mode or DSi main RAM in DSi mode. Agb-/TwlBg clears bit 0 in reg 0x10201000 before touching this reg.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=I2S_Registers&diff=21102
I2S Registers
2019-11-26T14:38:26Z
<p>Profi200: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#I2S_CNT|I2S_CNT]]?<br />
| 0x10145000<br />
| 2<br />
| codec module, AgbBg, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#?|?]]<br />
| 0x10145002<br />
| 2<br />
| codec module, AgbBg, TwlBg<br />
|}<br />
<br />
<br />
==I2S_CNT==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0-5<br />
| DSP volume (doesn't affect csnd)<br />
|-<br />
| 6-11<br />
| Another volume?<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13-14<br />
| ?<br />
|-<br />
| 15<br />
| Enable (0=Disabled, 1=Enabled)<br />
|}<br />
<br />
This is usually set to 0xC800 or 0xC820 when the DSP is active.<br />
<br />
<br />
==?==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 13-14<br />
| ?<br />
|-<br />
| 15<br />
| Enable (0=Disabled, 1=Enabled)<br />
|}<br />
<br />
Usually set to 0xE000.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=I2S_Registers&diff=21101
I2S Registers
2019-11-26T14:37:14Z
<p>Profi200: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#I2S_CNT|I2S_CNT]]?<br />
| 0x10145000<br />
| 2<br />
| codec module, AgbBg, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#?|?]]<br />
| 0x10145002<br />
| 2<br />
| codec module, AgbBg, TwlBg<br />
|}<br />
<br />
==I2S_CNT==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0-5<br />
| DSP volume (doesn't affect csnd)<br />
|-<br />
| 6-11<br />
| Another volume?<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13-14<br />
| ?<br />
|-<br />
| 15<br />
| Enable (0=Disabled, 1=Enabled)<br />
|}<br />
<br />
This is usually set to 0xC800 or 0xC820 when the DSP is active.<br />
<br />
<br />
==?==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 13-14<br />
| ?<br />
|-<br />
| 15<br />
| Enable (0=Disabled, 1=Enabled)<br />
|}<br />
<br />
Usually set to 0xE000.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=21009
SPI Registers
2019-06-27T23:45:18Z
<p>Profi200: /* Registers */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]1<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]1<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]1<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]1<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]1<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]1<br />
| 0x10142814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]1<br />
| 0x10142818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]1<br />
| 0x1014281C<br />
| 4<br />
| -<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]2<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]2<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]2<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]2<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]2<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]2<br />
| 0x10143814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]2<br />
| 0x10143818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]2<br />
| 0x1014381C<br />
| 4<br />
| -<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]3<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA3<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]3<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]3<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]3<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]3<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]3<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]3<br />
| 0x10160814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]3<br />
| 0x10160818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]3<br />
| 0x1016081C<br />
| 4<br />
| -<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== NSPI_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Clock<br />
|-<br />
| 6-7<br />
| Device select<br />
|-<br />
| 12<br />
| Bus mode (0 = 1 bit, 1 = 4 bit)<br />
|-<br />
| 13<br />
| Transfer direction (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| 1 = Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Bus<br />
! Device select<br />
! Clock<br />
|-<br />
| 0<br />
| 3<br />
| 0<br />
| 2<br />
|-<br />
| 1, 2<br />
| 3<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 3<br />
| 1<br />
| 0<br />
| 5<br />
|-<br />
| 4, 5<br />
| 1<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 6<br />
| 2<br />
| 0<br />
| ?<br />
|}<br />
<br />
== NSPI_DONE ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Chip select<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO full (0 = not full, 1 = full)<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
At transfer start and every 32 bytes the FIFO becomes busy.<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Clock (from [[#NSPI_CNT|NSPI_CNT]]) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (also fires on each autopoll try?)<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[ARM11_Interrupts#Hardware_Interrupts|Interrupt]] ID 0x24, 0x56 or 0x57 (depending on the bus) is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=21008
SPICARD Registers
2019-06-27T23:42:04Z
<p>Profi200: /* Registers */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! RW<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]<br />
| 0x1000D800<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]<br />
| 0x1000D804<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]<br />
| 0x1000D808<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]<br />
| 0x1000D80C<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]<br />
| 0x1000D810<br />
| 4<br />
| R<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]<br />
| 0x1000D814<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]<br />
| 0x1000D818<br />
| 4<br />
| W?<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]<br />
| 0x1000D81C<br />
| 4<br />
| RW<br />
|<br />
|}<br />
<br />
== NSPI_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-2<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading this register.<br />
<br />
== NSPI_DONE ==<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs. Nintendo uses a timeout of 10 which roughly equals 1 second. This is used in Process9 to poll the gamecard SPI flash status register for write operation finished or write enable.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished (also fires on each autopoll try?)<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[IRQ_Registers|Interrupt]] ID 23 is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=21007
ARM11 Interrupts
2019-06-27T20:11:22Z
<p>Profi200: /* Hardware Interrupts */</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF. A priority of 0xF means that the interrupt is disabled.<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0<br />
| <br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0x1<br />
| <br />
| MPCore software-interrupt. Used by BOOT11 to kickstart Core1.<br />
|-<br />
| 0x2-0x3<br />
| <br />
| MPCore software-interrupt. Seem to be unused.<br />
|-<br />
| 0x4<br />
| Kernel<br />
| MPCore software-interrupt. Used to manage the performance counter.<br />
|-<br />
| 0x5<br />
| Kernel<br />
| MPCore software-interrupt. Does apparently nothing.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).<br />
|-<br />
| 0x7<br />
| Kernel<br />
| MPCore software-interrupt. See [[KCacheMaintenanceInterruptEvent]]<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9<br />
| Kernel<br />
| MPCore software-interrupt. Used when handling exceptions that require termination of a thread or a process, and in some cases by svcSetDebugThreadContext, to store VFP registers in the thread's register storage.<br />
|-<br />
| 0xA<br />
| Kernel<br />
| TLB operations interrupt, see [[KTLBOperationsInterruptEvent]]<br />
|-<br />
| 0xB-0xE<br />
|<br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything.<br />
|}<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x24<br />
| ?<br />
| SPI bus 2 interrupt status update<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0 (VBlank0)<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1 (VBlank1)<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| P3D<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| General interrupt from DSP, including semaphore and command/reply registers status change<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| Y2R2 End Event<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| Related to mvd services<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| I2C Bus0 work done<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| I2C Bus1 work done<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| SPI bus 3 interrupt status update<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| SPI bus 1 interrupt status update<br />
|-<br />
| 0x58<br />
| Kernel<br />
| PDN<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| I2C Bus2 work done<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Shell opened<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Shell closed<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU (HOME/POWER pressed/released or WiFi switch pressed)<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|-<br />
| 0x78 to 0x7B<br />
| Kernel<br />
| Core 0-3 Performance monitor counter (any) overflow<br />
|-<br />
| 0x7A to 0x82 (PDN_MPCORE_CFG bit2 set) or<br />
0x7C to 0x84 (bit2 clear)<br />
| Kernel<br />
| ?<br />
|}<br />
(interrupts from 0x80 and up can't be mapped in available builds of the kernel)<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| [[KBaseInterruptEvent]] *<br />
| Pointer to the KBaseInterruptEvent object for this interrupt <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt will be disabled by the IRQ handler as soon as it is acknowledged.<br />
Ignored for FIQ: the FIQ handler always sets bit2 of [[PDN_Registers#PDN_FIQ_CNT|PDN_FIQ_CNT]]<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is disabled<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptData[224]<br />
| Data for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| [[KObjectMutex]]<br />
| Mutex<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=20999
CONFIG11 Registers
2019-06-08T23:26:07Z
<p>Profi200: /* CFG11_GPU_CNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_0|CFG11_TWLMODE_0]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_1|CFG11_TWLMODE_1]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_2|CFG11_TWLMODE_2]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_HID|CFG11_TWLMODE_HID]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_GPU_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160000.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142000.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143000.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==CFG11_TWLMODE_0==<br />
Observed 0x8001 when running under TWL_ and AGB_FIRM, 0 NATIVE_FIRM.<br />
<br />
This address is poked from ARM7 to signal that it has booted and begun executing code. The ARM7-mode address for this register is 0x4700000.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
Writing 0x8000 to here from the ARM9 with NATIVE_FIRM running doesn't seem to do anything, other reg-pokes likely need done first.<br />
<br />
==CFG11_TWLMODE_1==<br />
Observed 0x8000 when running under TWL_FIRM, 0 NATIVE_FIRM.<br />
<br />
==CFG11_TWLMODE_2==<br />
Bitfield.<br />
<br />
==CFG11_TWLMODE_HID==<br />
The value of this register is copied to [[HID_Registers|HID_?]] under certain conditions.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_GPU_CNT==<br />
This one seems to control the LCD/GPU/Backlight.<br />
<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
When this is unset VRAM is not accessible and triggers exceptions.<br />
<br />
Bits 1..6: other nRESET bits.<br />
<br />
Bit16: Enable/Turn on LCD backlight.<br />
<br />
PDN uses a 12 Arm11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_GPU_FCRAM_CNT==<br />
Bit1: Enable/disable FCRAM.<br />
Bit2: Enable/disable operation in progress.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=NDMA_Registers&diff=20970
NDMA Registers
2019-05-15T19:46:42Z
<p>Profi200: /* Startup modes (27-24) */</p>
<hr />
<div>3DS NDMA has 8 channels. The first 0x100-bytes of this IO mem is mirrored at 0x10002100, repeated every 0x100-bytes until the end of the 0x1000-byte IO mem. NDMA can access the ARM9 bootrom, including the protected part before it is locked out.<br />
<br />
= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_GLOBAL_CNT|NDMA_GLOBAL_CNT]]<br />
| 0x10002000<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_SRC_ADDR|NDMA_SRC_ADDR]](n)<br />
| 0x10002004 + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_DST_ADDR|NDMA_DST_ADDR]](n)<br />
| 0x10002008 + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_TRANSFER_CNT|NDMA_TRANSFER_CNT]](n)<br />
| 0x1000200c + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_WRITE_CNT|NDMA_WRITE_CNT]](n)<br />
| 0x10002010 + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_BLOCK_CNT|NDMA_BLOCK_CNT]](n)<br />
| 0x10002014 + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_FILL_DATA|NDMA_FILL_DATA]](n)<br />
| 0x10002018 + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NDMA_CNT|NDMA_CNT]](n)<br />
| 0x1000201C + (n*0x1c)<br />
| 4<br />
| Boot9, Kernel9<br />
|}<br />
<br />
== NDMA_GLOBAL_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Global enable?<br />
|-<br />
| 19-16<br />
| Cycle selection.<br />
|-<br />
| 31<br />
| DMA arbitration method. 0=Fixed method, 1=Round robin<br />
|}<br />
<br />
== NDMA_SRC_ADDR ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-0<br />
| Source data address. Must be multiple of 4.<br />
|}<br />
Like old DMA, NDMA_SRC_ADDR is copied to internal registers when written to.<br />
<br />
== NDMA_DST_ADDR ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Destination data address. Must be multiple of 4.<br />
|}<br />
Like old DMA, NDMA_DST_ADDR is copied to internal registers when written to.<br />
<br />
== NDMA_TRANSFER_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 27-0<br />
| Total number of words transferred.<br />
|}<br />
<br />
== NDMA_WRITE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 23-0<br />
| Number of words to transfer.<br />
|}<br />
<br />
== NDMA_BLOCK_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 15-0<br />
| Interval timer.<br />
|-<br />
| 17-16<br />
| Prescaler. 0=System freq, 1=1/4th freq, 2=1/16th freq, 3=1/64th freq.<br />
|}<br />
<br />
== NDMA_FILL_DATA ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 31-0<br />
| Fill data.<br />
|}<br />
<br />
== NDMA_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 11-10<br />
| Destination address update method. 0=Increment, 1=Decrement, 2=Fixed.<br />
|-<br />
| 12<br />
| Destination address reload flag.<br />
|-<br />
| 14-13<br />
| Source address update method. 0=Increment, 1=Decrement, 2=Fixed, 3=No address (for filling)<br />
|-<br />
| 15<br />
| Source address reload flag.<br />
|-<br />
| 19-16<br />
| Block transfer word count = (1<<x) words.<br />
|-<br />
| 27-24<br />
| Startup mode.<br />
|-<br />
| 28<br />
| Immediate mode.<br />
|-<br />
| 29<br />
| Repeating mode.<br />
|-<br />
| 30<br />
| IRQ enable<br />
|-<br />
| 31<br />
| Enable/busy flag.<br />
|}<br />
<br />
== Startup modes (27-24) ==<br />
{| class="wikitable" border="1"<br />
! Value<br />
! Description<br />
|-<br />
| 0<br />
| TIMER0<br />
|-<br />
| 1<br />
| TIMER1<br />
|-<br />
| 2<br />
| TIMER2<br />
|-<br />
| 3<br />
| TIMER3<br />
|-<br />
| 4<br />
| CTRCARD0<br />
|-<br />
| 5<br />
| CTRCARD1<br />
|-<br />
| 6<br />
| MMC1<br />
|-<br />
| 7<br />
| MMC2?<br />
|-<br />
| 8<br />
| AES in ([[AES_Registers#AES_WRFIFO.2FAES_RDFIFO|WRFIFO]])<br />
|-<br />
| 9<br />
| AES out ([[AES_Registers#AES_WRFIFO.2FAES_RDFIFO|RDFIFO]])<br />
|-<br />
| 10<br />
| SHA in ([[SHA_Registers#SHA_FIFO|INFIFO]])<br />
|-<br />
| 11<br />
| SHA out ([[SHA_Registers#SHA_FIFO|INFIFO]])<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13<br />
| ?<br />
|-<br />
| 14<br />
| ?<br />
|-<br />
| 15<br />
| MMC1 + AES + SHA combined?<br />
|}<br />
<br />
== Block transfers ==<br />
First, a word is always 32 bits. Second, the block transfer specified in NDMA_CNT is the smallest atom of data that will be transferred in a burst. The bus is monopolized until this block is transferred, without splitting up.<br />
<br />
The next block transfer will happen after the specified time in the NDMA_BLOCK_CNT interval timer, until done.<br />
<br />
== Immediate mode ==<br />
Transfers the words specified in NDMA_WRITE_CNT immediately following block transfer rules. NDMA_TRANSFER_CNT and repeating mode are ignored.<br />
<br />
== Repeating mode ==<br />
Transfers the words specified in NDMA_WRITE_CNT following the startup mode event. NDMA_TRANSFER_CNT is ignored.<br />
<br />
== No immediate and no repeating mode ==<br />
Transfers the words specified in NDMA_WRITE_CNT for each startup event, and gets disabled when the total number of words in NDMA_TRANSFER_CNT are transferred.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SHA_Registers&diff=20969
SHA Registers
2019-05-15T18:44:40Z
<p>Profi200: /* SHA_CNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SHA_CNT|SHA_CNT]]<br />
| 0x1000A000<br />
| 4<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SHA_BLKCNT|SHA_BLKCNT]]<br />
| 0x1000A004<br />
| 4<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SHA_HASH|SHA_HASH]]<br />
| 0x1000A040<br />
| 0x20<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SHA_FIFO|SHA_FIFO]]<br />
| 0x1000A080<br />
| 0x40<br />
| Boot9, Process9<br />
|}<br />
<br />
== SHA_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Start (1=enable/busy, 0=idle)<br />
|-<br />
| 1<br />
| Final round (1=enable/busy, 0=normal)<br />
|-<br />
| 2<br />
| Input DMA enable (1= enable, 0=disable)<br />
|-<br />
| 3<br />
| Output Endianess (0=little, 1=big)<br />
|-<br />
| 4-5<br />
| Mode (0=SHA256, 1=SHA224, 2=3=SHA1)<br />
|-<br />
| 6<br />
| ?<br />
|-<br />
| 7<br />
| ?<br />
|-<br />
| 8<br />
| Clear FIFO? When set, the *entire* ARM9 hangs/crashes when attempting to read SHA_INFIFO.<br />
|-<br />
| 9<br />
| Enable FIFO (1=fifo, 0=write-only)<br />
|-<br />
| 10<br />
| Output DMA enable (1= enable, 0=disable)<br />
|-<br />
| 16<br />
| ?<br />
|-<br />
| 17<br />
| ?<br />
|}<br />
<br />
Bit 8 is used when boot9 chains eMMC reads with AES and SHA to to load, decrypt and verify FIRM partitions.<br />
<br />
== SHA_BLKCNT ==<br />
This reg contains the total size of the data written to REG_SHA_IN, this field is updated when performing hash-function final-round.<br />
<br />
== SHA_HASH ==<br />
This reg contains the SHA* hash after the final round, and the internal state during normal rounds. It is possible to write the internal state using this register.<br />
<br />
== SHA_FIFO ==<br />
The data to be hashed must be written here. It does not matter what offset is written to.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=RSA_Registers&diff=20968
RSA Registers
2019-05-15T13:17:04Z
<p>Profi200: /* RSA_CNT */</p>
<hr />
<div>= Overview =<br />
<br />
The RSA module is essentially a hardware-accelerated modular exponentiation engine. It is specially optimized for RSA applications, so its behavior can be incoherent when RSA's invariants are broken.<br />
<br />
=== Observed edge cases ===<br />
* if 2 divides mod, output == 0<br />
<br />
= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_CNT|RSA_CNT]]<br />
| 0x1000B000<br />
| 0x04<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| RSA_?<br />
| 0x1000B0F0<br />
| 0x04<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_SLOT|RSA_SLOT]]0<br />
| 0x1000B100<br />
| 0x10<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_SLOT|RSA_SLOT]]1<br />
| 0x1000B110<br />
| 0x10<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_SLOT|RSA_SLOT]]2<br />
| 0x1000B120<br />
| 0x10<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_SLOT|RSA_SLOT]]3<br />
| 0x1000B130<br />
| 0x10<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_EXPFIFO|RSA_EXPFIFO]]<br />
| 0x1000B200<br />
| 0x100 (can handle u32 writes to any aligned position in the FIFO)<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_MOD|RSA_MOD]]<br />
| 0x1000B400<br />
| 0x100<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#RSA_TXT|RSA_TXT]]<br />
| 0x1000B800<br />
| 0x100<br />
|<br />
|}<br />
<br />
== RSA_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Start (1=Enable/Busy, 0=Idle)<br />
|-<br />
| 1<br />
| Interrupt enable (1=enable, 0=disable)<br />
|-<br />
| 4-7<br />
| Keyslot (Bit6-7 don't actually affect the keyslot)<br />
|-<br />
| 8<br />
| Endianness (1=Little endian, 0=Big endian). Affects RSA_EXPFIFO, RSA_MOD, and RSA_TXT.<br />
|-<br />
| 9<br />
| Word order (1=Normal order, 0=Reversed order). Affects RSA_MOD and RSA_TXT.<br />
|}<br />
<br />
== RSA_SLOT ==<br />
{| class="wikitable" border="1"<br />
! Name<br />
! Offset<br />
! Width<br />
|-<br />
| [[#RSA_SLOTCNT|RSA_SLOTCNT]]<br />
| 0x0<br />
| 0x4<br />
|-<br />
| [[#RSA_SLOTSIZE|RSA_SLOTSIZE]]<br />
| 0x4<br />
| 0x4<br />
|-<br />
| ?<br />
| 0x8<br />
| 0x4<br />
|-<br />
| ?<br />
| 0xC<br />
| 0x4<br />
|}<br />
<br />
== RSA_SLOTCNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Key status (1=Key has been set, 0=Key has not been set yet)<br />
|-<br />
| 1<br />
| Key write-protect, this bit is RW. (0 = no protection, 1 = protected)<br />
|-<br />
| 30-2<br />
| ?<br />
|-<br />
| 31<br />
| ?<br />
|}<br />
<br />
Before writing RSA_EXPFIFO/RSA_MOD, bit0 here should be cleared when bit31 is already clear. Otherwise, the ARM9 will hang when attempting to write to RSA_EXPFIFO.<br />
<br />
== RSA_SLOTSIZE ==<br />
This contains the RSA size for this slot, in words. Normally this is 0x40 for RSA-2048.<br />
<br />
== RSA_EXPFIFO ==<br />
The 0x100-byte private or public exponent is written to this write-only FIFO.<br />
<br />
== RSA_MOD ==<br />
The RSA key modulus for the selected keyslot can be written here. When writing the RSA modulus, the modulus must align with the end of the register area.<br />
<br />
Writing to RSA_MOD does not change the exponent written with RSA_EXPFIFO. An attack based on the [[wikipedia:Pohlig-Hellman algorithm|Pohlig-Hellman algorithm]] exists to "read" the contents of RSA_EXPFIFO as a result (see [[3DS System Flaws#Hardware|3DS System Flaws]]).<br />
<br />
== RSA_TXT ==<br />
The RSA signature can be written here, and the data read from here is the message. When writing the RSA signature, the signature must be prepended with zeroes until it is a multiple of 8 bytes, and the end of the signature must align with the end of the register area.<br />
<br />
The PKCS message padding must be manually checked by software, as hardware will only do raw RSA operations.<br />
<br />
== Keyslots usage ==<br />
{| class="wikitable" border="1"<br />
! Keyslot<br />
! Description<br />
|-<br />
| 0<br />
| Arbitrary<br />
|-<br />
| 1<br />
| [[NCCH#CXI|CXI]] access desc (following the exheader)<br />
|-<br />
| 2-3<br />
| Initialized by the ARM9 bootrom, but not used by any of the [[FIRM]]s. It's unknown what the ARM9 bootrom uses these for, if anything.<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20964
SPI Registers
2019-05-11T20:52:41Z
<p>Profi200: /* NSPI_AUTOPOLL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]1<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]1<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]1<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]1<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]1<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]1<br />
| 0x10142814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]1<br />
| 0x10142818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]1<br />
| 0x1014281C<br />
| 4<br />
| -<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]2<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]2<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]2<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]2<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]2<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]2<br />
| 0x10143814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]2<br />
| 0x10143818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]2<br />
| 0x1014381C<br />
| 4<br />
| -<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]3<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA3<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]3<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]3<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]3<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]3<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]3<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]3<br />
| 0x10160814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]3<br />
| 0x10160818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]3<br />
| 0x1016081C<br />
| 4<br />
| -<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== NSPI_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Clock<br />
|-<br />
| 6-7<br />
| Device select<br />
|-<br />
| 12<br />
| Bus mode (0 = 1 bit, 1 = 4 bit)<br />
|-<br />
| 13<br />
| Transfer direction (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| 1 = Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Bus<br />
! Device select<br />
! Clock<br />
|-<br />
| 0<br />
| 3<br />
| 0<br />
| 2<br />
|-<br />
| 1, 2<br />
| 3<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 3<br />
| 1<br />
| 0<br />
| 5<br />
|-<br />
| 4, 5<br />
| 1<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 6<br />
| 2<br />
| 0<br />
| ?<br />
|}<br />
<br />
== NSPI_DONE ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Chip select<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO full (0 = not full, 1 = full)<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
At transfer start and every 32 bytes the FIFO becomes busy.<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Clock (from [[#NSPI_CNT|NSPI_CNT]]) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished? (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished?<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[ARM11_Interrupts#Hardware_Interrupts|Interrupt]] ID 0x56 or 0x57 (depending on the bus) is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=20963
ARM11 Interrupts
2019-05-11T20:45:31Z
<p>Profi200: /* Hardware Interrupts */ Oops</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF. A priority of 0xF means that the interrupt is disabled.<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0<br />
| <br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0x1<br />
| <br />
| MPCore software-interrupt. Used by BOOT11 to kickstart Core1.<br />
|-<br />
| 0x2-0x3<br />
| <br />
| MPCore software-interrupt. Seem to be unused.<br />
|-<br />
| 0x4<br />
| Kernel<br />
| MPCore software-interrupt. Used to manage the performance counter.<br />
|-<br />
| 0x5<br />
| Kernel<br />
| MPCore software-interrupt. Does apparently nothing.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).<br />
|-<br />
| 0x7<br />
| Kernel<br />
| MPCore software-interrupt. See [[KCacheMaintenanceInterruptEvent]]<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9<br />
| Kernel<br />
| MPCore software-interrupt. Used when handling exceptions that require termination of a thread or a process, and in some cases by svcSetDebugThreadContext, to store VFP registers in the thread's register storage.<br />
|-<br />
| 0xA<br />
| Kernel<br />
| TLB operations interrupt, see [[KTLBOperationsInterruptEvent]]<br />
|-<br />
| 0xB-0xE<br />
|<br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything.<br />
|}<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0 (VBlank0)<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1 (VBlank1)<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| P3D<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| General interrupt from DSP, including semaphore and command/reply registers status change<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| Y2R2 End Event<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| Related to mvd services<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| I2C Bus0 work done<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| I2C Bus1 work done<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| SPI bus 3 interrupt status update<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| SPI bus 1 interrupt status update<br />
|-<br />
| 0x58<br />
| Kernel<br />
| PDN<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| I2C Bus2 work done<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Shell opened<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Shell closed<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU (HOME/POWER pressed/released or WiFi switch pressed)<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|-<br />
| 0x78 to 0x7B<br />
| Kernel<br />
| Core 0-3 Performance monitor counter (any) overflow<br />
|-<br />
| 0x7A to 0x82 (PDN_MPCORE_CFG bit2 set) or<br />
0x7C to 0x84 (bit2 clear)<br />
| Kernel<br />
| ?<br />
|}<br />
(interrupts from 0x80 and up can't be mapped in available builds of the kernel)<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| [[KBaseInterruptEvent]] *<br />
| Pointer to the KBaseInterruptEvent object for this interrupt <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt will be disabled by the IRQ handler as soon as it is acknowledged.<br />
Ignored for FIQ: the FIQ handler always sets bit2 of [[PDN_Registers#PDN_FIQ_CNT|PDN_FIQ_CNT]]<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is disabled<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptData[224]<br />
| Data for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| [[KObjectMutex]]<br />
| Mutex<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=20962
ARM11 Interrupts
2019-05-11T20:43:40Z
<p>Profi200: /* Hardware Interrupts */</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF. A priority of 0xF means that the interrupt is disabled.<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0<br />
| <br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0x1<br />
| <br />
| MPCore software-interrupt. Used by BOOT11 to kickstart Core1.<br />
|-<br />
| 0x2-0x3<br />
| <br />
| MPCore software-interrupt. Seem to be unused.<br />
|-<br />
| 0x4<br />
| Kernel<br />
| MPCore software-interrupt. Used to manage the performance counter.<br />
|-<br />
| 0x5<br />
| Kernel<br />
| MPCore software-interrupt. Does apparently nothing.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).<br />
|-<br />
| 0x7<br />
| Kernel<br />
| MPCore software-interrupt. See [[KCacheMaintenanceInterruptEvent]]<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9<br />
| Kernel<br />
| MPCore software-interrupt. Used when handling exceptions that require termination of a thread or a process, and in some cases by svcSetDebugThreadContext, to store VFP registers in the thread's register storage.<br />
|-<br />
| 0xA<br />
| Kernel<br />
| TLB operations interrupt, see [[KTLBOperationsInterruptEvent]]<br />
|-<br />
| 0xB-0xE<br />
|<br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything.<br />
|}<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0 (VBlank0)<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1 (VBlank1)<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| P3D<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| General interrupt from DSP, including semaphore and command/reply registers status change<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| Y2R2 End Event<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| Related to mvd services<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| I2C Bus0 work done<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| I2C Bus1 work done<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| SPI bus 3 interrupt status update<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| SPI bus 0 interrupt status update<br />
|-<br />
| 0x58<br />
| Kernel<br />
| PDN<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| I2C Bus2 work done<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Shell opened<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Shell closed<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU (HOME/POWER pressed/released or WiFi switch pressed)<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|-<br />
| 0x78 to 0x7B<br />
| Kernel<br />
| Core 0-3 Performance monitor counter (any) overflow<br />
|-<br />
| 0x7A to 0x82 (PDN_MPCORE_CFG bit2 set) or<br />
0x7C to 0x84 (bit2 clear)<br />
| Kernel<br />
| ?<br />
|}<br />
(interrupts from 0x80 and up can't be mapped in available builds of the kernel)<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| [[KBaseInterruptEvent]] *<br />
| Pointer to the KBaseInterruptEvent object for this interrupt <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt will be disabled by the IRQ handler as soon as it is acknowledged.<br />
Ignored for FIQ: the FIQ handler always sets bit2 of [[PDN_Registers#PDN_FIQ_CNT|PDN_FIQ_CNT]]<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is disabled<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptData[224]<br />
| Data for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| [[KObjectMutex]]<br />
| Mutex<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20961
SPI Registers
2019-05-11T20:41:17Z
<p>Profi200: /* Registers */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]1<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]1<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]1<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]1<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]1<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]1<br />
| 0x10142814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]1<br />
| 0x10142818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]1<br />
| 0x1014281C<br />
| 4<br />
| -<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]2<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]2<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]2<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]2<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]2<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]2<br />
| 0x10143814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]2<br />
| 0x10143818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]2<br />
| 0x1014381C<br />
| 4<br />
| -<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]3<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA3<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]3<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]3<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]3<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]3<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]3<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]3<br />
| 0x10160814<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]3<br />
| 0x10160818<br />
| 4<br />
| -<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]3<br />
| 0x1016081C<br />
| 4<br />
| -<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== NSPI_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Clock<br />
|-<br />
| 6-7<br />
| Device select<br />
|-<br />
| 12<br />
| Bus mode (0 = 1 bit, 1 = 4 bit)<br />
|-<br />
| 13<br />
| Transfer direction (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| 1 = Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Bus<br />
! Device select<br />
! Clock<br />
|-<br />
| 0<br />
| 3<br />
| 0<br />
| 2<br />
|-<br />
| 1, 2<br />
| 3<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 3<br />
| 1<br />
| 0<br />
| 5<br />
|-<br />
| 4, 5<br />
| 1<br />
| 1, 2<br />
| ?, ?<br />
|-<br />
| 6<br />
| 2<br />
| 0<br />
| ?<br />
|}<br />
<br />
== NSPI_DONE ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Chip select<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO full (0 = not full, 1 = full)<br />
|-<br />
| 1-31<br />
| Unused<br />
|}<br />
<br />
At transfer start and every 32 bytes the FIFO becomes busy.<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished? (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished?<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[ARM11_Interrupts#Hardware_Interrupts|Interrupt]] ID 0x56 or 0x57 (depending on the bus) is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=20960
SPICARD Registers
2019-05-09T18:51:19Z
<p>Profi200: /* Registers */ Bit range consistency.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! RW<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]<br />
| 0x1000D800<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]<br />
| 0x1000D804<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]<br />
| 0x1000D808<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]<br />
| 0x1000D80C<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]<br />
| 0x1000D810<br />
| 4<br />
| R<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]<br />
| 0x1000D814<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]<br />
| 0x1000D818<br />
| 4<br />
| W?<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]<br />
| 0x1000D81C<br />
| 4<br />
| RW<br />
|<br />
|}<br />
<br />
== NSPI_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-2<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading this register.<br />
<br />
== NSPI_DONE ==<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-31<br />
| Data<br />
|}<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs. Nintendo uses a timeout of 10 which roughly equals 1 second. This is used in Process9 to poll the gamecard SPI flash status register for write operation finished or write enable.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished? (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished?<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[IRQ_Registers|Interrupt]] ID 23 is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=20959
SPICARD Registers
2019-05-09T18:49:01Z
<p>Profi200: /* NSPI_BLKLEN */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! RW<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]<br />
| 0x1000D800<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]<br />
| 0x1000D804<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]<br />
| 0x1000D808<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]<br />
| 0x1000D80C<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]<br />
| 0x1000D810<br />
| 4<br />
| R<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]<br />
| 0x1000D814<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]<br />
| 0x1000D818<br />
| 4<br />
| W?<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]<br />
| 0x1000D81C<br />
| 4<br />
| RW<br />
|<br />
|}<br />
<br />
== NSPI_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 2-0<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading this register.<br />
<br />
== NSPI_DONE ==<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-20<br />
| Transfer size<br />
|-<br />
| 21-31<br />
| Unused<br />
|}<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Data<br />
|}<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs. Nintendo uses a timeout of 10 which roughly equals 1 second. This is used in Process9 to poll the gamecard SPI flash status register for write operation finished or write enable.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished? (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished?<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[IRQ_Registers|Interrupt]] ID 23 is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=20958
SPICARD Registers
2019-05-09T15:23:44Z
<p>Profi200: /* Registers */ Added missing registers.</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! RW<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]<br />
| 0x1000D800<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]<br />
| 0x1000D804<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]<br />
| 0x1000D808<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]<br />
| 0x1000D80C<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]<br />
| 0x1000D810<br />
| 4<br />
| R<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_AUTOPOLL|NSPI_AUTOPOLL]]<br />
| 0x1000D814<br />
| 4<br />
| RW<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_MASK|NSPI_INT_MASK]]<br />
| 0x1000D818<br />
| 4<br />
| W?<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_INT_STAT|NSPI_INT_STAT]]<br />
| 0x1000D81C<br />
| 4<br />
| RW<br />
|<br />
|}<br />
<br />
== NSPI_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 2-0<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading this register.<br />
<br />
== NSPI_DONE ==<br />
Contains 1 when the SPI slave is selected. A 0 is written here on transfer end to deselect the slave.<br />
<br />
== NSPI_BLKLEN ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Transfer size<br />
|}<br />
<br />
== NSPI_FIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Data<br />
|}<br />
<br />
== NSPI_STATUS ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}<br />
<br />
== NSPI_AUTOPOLL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-7<br />
| Command<br />
|-<br />
| 16-19<br />
| Timeout (Tries = 31<<Baudrate (from NSPI_CNT) + Timeout)<br />
|-<br />
| 24-26<br />
| Bit offset (0-7)<br />
|-<br />
| 30<br />
| Poll for a set or unset bit<br />
|-<br />
| 31<br />
| 1 = Enable/Busy<br />
|}<br />
<br />
This automatically sends a command to the device and compares the specified bit in the response with bit 30 until it matches or a timeout occurs. Nintendo uses a timeout of 10 which roughly equals 1 second. This is used in Process9 to poll the gamecard SPI flash status register for write operation finished or write enable.<br />
<br />
== NSPI_INT_MASK ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished? (1 = disabled)<br />
|-<br />
| 1<br />
| Autopoll success (1 = disabled)<br />
|-<br />
| 2<br />
| Autopoll timeout (1 = disabled)<br />
|}<br />
<br />
== NSPI_INT_STAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Transfer finished?<br />
|-<br />
| 1<br />
| Autopoll success<br />
|-<br />
| 2<br />
| Autopoll timeout<br />
|}<br />
<br />
[[IRQ_Registers|Interrupt]] ID 23 is fired when any of the bits change to 1 except for interrupts masked in [[#NSPI_INT_MASK|NSPI_INT_MASK]]. Writing 1 to a bit in this register aknowledges the interrupt.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPICARD_Registers&diff=20957
SPICARD Registers
2019-05-08T00:05:00Z
<p>Profi200: /* REG_SPICARDCNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#REG_SPICARDCNT|REG_SPICARDCNT]]<br />
| 0x1000D800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#REG_SPICARDASSERT|REG_SPICARDASSERT]]<br />
| 0x1000D804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#REG_SPICARDSIZE|REG_SPICARDSIZE]]<br />
| 0x1000D808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#REG_SPICARDFIFO|REG_SPICARDFIFO]]<br />
| 0x1000D80C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#REG_SPICARDFIFOSTAT|REG_SPICARDFIFOSTAT]]<br />
| 0x1000D810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x1000D814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x1000D818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x1000D81C<br />
| 4<br />
|<br />
|}<br />
<br />
== REG_SPICARDCNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 2-0<br />
| [[Filesystem_services#CardSpiBaudRate|Baud Rate]]<br />
|-<br />
| 6-7<br />
| Unused device select.<br />
|-<br />
| 12<br />
| [[Filesystem_services#CardSpiBusMode|Bus Mode]]<br />
|-<br />
| 13<br />
| Transfer Mode (0 = read, 1 = write)<br />
|-<br />
| 15<br />
| Trigger (0 = idle, 1 = busy)<br />
|}<br />
<br />
This register seems to have a bug where the lower 8 bits are shifted up by 16 when reading them back.<br />
<br />
== REG_SPICARDASSERT ==<br />
When deasserting the card, this registers is set to 0. Presumably contains 1 when the card is asserted.<br />
<br />
== REG_SPICARDSIZE ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Transfer size<br />
|}<br />
<br />
== REG_SPICARDFIFO ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 31-0<br />
| Data<br />
|}<br />
<br />
== REG_SPICARDFIFOSTAT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| FIFO Full (0 = not full, 1 = full)<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20956
SPI Registers
2019-05-07T18:36:22Z
<p>Profi200: /* Registers */ Use same naming scheme as NDMA</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10142814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10142818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014281C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10143814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10143818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014381C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_CNT|NSPI_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_DONE|NSPI_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_BLKLEN|NSPI_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_FIFO|NSPI_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#NSPI_STATUS|NSPI_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10160814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10160818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1016081C<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== NSPI_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| Bus mode 0=1 bit, 1=4 bit<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== NSPI_DONE ==<br />
This register reads as 1 after starting a transfer. When the transfer is finished, a 0 has to be written to this register. This is probably the Chip Select line.<br />
<br />
==NSPI_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==NSPI_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==NSPI_STATUS==<br />
Bit0: FIFO busy. At transfer start and every 32 bytes the FIFO becomes busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20955
SPI Registers
2019-05-07T18:25:48Z
<p>Profi200: /* SPI_NEW_CNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10142814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10142818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014281C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10143814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10143818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014381C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10160814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10160818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1016081C<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| Bus mode 0=1 bit, 1=4 bit<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
This register reads as 1 after starting a transfer. When the transfer is finished, a 0 has to be written to this register. This is probaly the Chip Select line.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy. At transfer start and every 32 bytes the FIFO becomes busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20954
SPI Registers
2019-05-07T17:37:45Z
<p>Profi200: /* Registers */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10142814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10142818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014281C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10143814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10143818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1014381C<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Same as [[SPICARD_Registers|SPICARD]] + 0x814. Unused by SPI sysmodule.<br />
| 0x10160814<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x10160818<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ? Unused by SPI sysmodule.<br />
| 0x1016081C<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
This register reads as 1 after starting a transfer. When the transfer is finished, a 0 has to be written to this register. This is probaly the Chip Select line.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy. At transfer start and every 32 bytes the FIFO becomes busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG11_Registers&diff=20953
CONFIG11 Registers
2019-05-07T16:03:49Z
<p>Profi200: /* Registers */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_DATA|CFG11_SHAREDWRAM_32K_DATA]]<0-7><br />
| 0x10140000<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SHAREDWRAM_32K_CODE|CFG11_SHAREDWRAM_32K_CODE]]<0-7><br />
| 0x10140008<br />
| 1*8<br />
| Boot11, Process9, [[DSP Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140100<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140102<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_FIQ_CNT|CFG11_FIQ_CNT]]<br />
| 0x10140104<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140105<br />
| 1<br />
| Kernel11.<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x10140108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| Related to [[HID_Registers|HID_?]]<br />
| 0x1014010C<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPUPROT|CFG11_GPUPROT]]<br />
| 0x10140140<br />
| 4<br />
| Kernel11<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFICNT|CFG11_WIFICNT]]<br />
| 0x10140180<br />
| 1<br />
| TwlBg, [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_SPI_CNT|CFG11_SPI_CNT]]<br />
| 0x101401C0<br />
| 2<br />
| [[SPI Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10140200<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140400<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| Clock related?<br />
| 0x10140410<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_CNT|CFG11_BOOTROM_OVERLAY_CNT]]<br />
| 0x10140420<br />
| 1<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]<br />
| 0x10140424<br />
| 4<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| ?<br />
| 0x10140428<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_SOCINFO|CFG11_SOCINFO]]<br />
| 0x10140FFC<br />
| 2<br />
| Boot11, Kernel11<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| CFG11_GPU_STATUS<br />
| 0x10141000<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_0<br />
| 0x10141008<br />
| 4<br />
| [[PTM Services]], [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_PTM_1<br />
| 0x1014100C<br />
| 4<br />
| [[PTM Services]], TwlBg, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_0|CFG11_TWLMODE_0]]<br />
| 0x10141100<br />
| 2<br />
| TwlProcess9, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_1|CFG11_TWLMODE_1]]<br />
| 0x10141104<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_2|CFG11_TWLMODE_2]]<br />
| 0x10141108<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_TWLMODE_HID|CFG11_TWLMODE_HID]]<br />
| 0x1014110A<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_WIFIUNK|CFG11_WIFIUNK]]<br />
| 0x1014110C<br />
| 1<br />
| [[NWM Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141110<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141112<br />
| 2<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_0]]<br />
| 0x10141114<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC|CFG11_CODEC_1]]<br />
| 0x10141116<br />
| 2<br />
| [[Codec Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141118<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141119<br />
| 1<br />
| TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10141120<br />
| 1<br />
| TwlBg<br />
|-<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT|CFG11_GPU_CNT]]<br />
| 0x10141200<br />
| 4<br />
| Boot11, Kernel11, [[PDN Services]], TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_GPU_CNT2|CFG11_GPU_CNT2]]<br />
| 0x10141204<br />
| 4<br />
| Boot11, Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| CFG11_GPU_FCRAM_CNT<br />
| 0x10141210<br />
| 2<br />
| Kernel11, TwlBg<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CODEC_CNT|CFG11_CODEC_CNT]]<br />
| 0x10141220<br />
| 1<br />
| Boot11, TwlBg, [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_CAMERA_CNT|CFG11_CAMERA_CNT]]<br />
| 0x10141224<br />
| 1<br />
| [[PDN Services]]<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG11_DSP_CNT|CFG11_DSP_CNT]]<br />
| 0x10141230<br />
| 1<br />
| Process9, [[PDN Services]]<br />
|-style="border-top: double"<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CLKCNT|CFG11_MPCORE_CLKCNT]]<br />
| 0x10141300<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_CNT|CFG11_MPCORE_CNT]]<br />
| 0x10141304<br />
| 2<br />
| NewKernel11<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG11_MPCORE_BOOTCNT<0-3>|CFG11_MPCORE_BOOTCNT]]<0-3><br />
| 0x10141310<br />
| 1*4<br />
| NewKernel11<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_DATA ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/data)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_SHAREDWRAM_32K_CODE ==<br />
Used for mapping 32K chunks of shared WRAM for DSP data.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0-1<br />
| Master (0=ARM9?, 1=ARM11?, 2 or 3=DSP/code)<br />
|-<br />
| 2-4<br />
| Offset (0..7) (slot 0..7) (LSB of address in 32Kbyte units)<br />
|-<br />
| 5-6<br />
| Not used (0)<br />
|-<br />
| 7<br />
| Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== CFG11_FIQ_CNT ==<br />
Writing bit1 to this register disables FIQ interrupts.<br />
<br />
This bit is set upon receipt of a FIQ interrupt and when [[SVC|svcUnbindInterrupt]] is called on the FIQ-abstraction [[ARM11_Interrupts#Private_Interrupts|software interrupt]] for the current core.<br />
It is cleared when binding that software interrupt to an event and just before that event is signaled.<br />
<br />
== CFG11_SPI_CNT ==<br />
When the corresponding bit is 0, the bus has to be accessed using the DS SPI registers. Otherwise it has to be accessed using the 3DS SPI registers.<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
|-<br />
| 0<br />
| Enable [[SPI Registers]] 0x10160000.<br />
|-<br />
| 1<br />
| Enable [[SPI Registers]] 0x10142000.<br />
|-<br />
| 2<br />
| Enable [[SPI Registers]] 0x10143000.<br />
|}<br />
<br />
== CFG11_BOOTROM_OVERLAY_CNT ==<br />
Bit0: Enable bootrom overlay functionality.<br />
<br />
== CFG11_BOOTROM_OVERLAY_VAL ==<br />
The 32-bit value to overlay data-reads to bootrom with. See [[#CFG11_MPCORE_BOOTCNT|CFG11_MPCORE_BOOTCNT]].<br />
<br />
== CFG11_SOCINFO ==<br />
Read-only register.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| 1 on both Old3DS and New3DS.<br />
| Boot11<br />
|-<br />
| 1<br />
| 1 on New3DS.<br />
| Kernel11<br />
|-<br />
| 2<br />
| Clock modifier: if set, use a 3x multiplier, otherwise 2x<br />
| Kernel11<br />
|}<br />
<br />
== CFG11_MPCORE_CLKCNT ==<br />
This is used for configuring the New3DS ARM11 CPU clock-rate. This register is New3DS-only: reading from here on Old3DS always returns all-zeros even when one tried writing data here prior to the read.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable clock multiplier? This must be set to 1 before writing a non-zero value to bit1-2, otherwise freeze. This enables the New 3DS FCRAM extension.<br />
|-<br />
| 1-2<br />
| Clock multiplier (0=1x, 1=2x, 2=3x, 3=hang)<br />
|-<br />
| 15<br />
| Busy<br />
|}<br />
<br />
[[SVC#KernelSetState|svcKernelSetState]] type10, only implemented on New3DS, uses this register. That code writes the following values to this register, depending on the input Param0 bit0 state, and the state of CFG11_SOCINFO:<br />
{| class="wikitable" border="1"<br />
! Register value<br />
! Higher-clockrate bit set in svcKernelSetState Param0<br />
! CFG11_SOCINFO bit2 set<br />
! MPCore timer/watchdog prescaler value, prior to subtracting it by 0x1 when writing it into hw/state<br />
! Clock-rate multiplier<br />
! Description<br />
|-<br />
| 0x01<br />
| No<br />
| Yes<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x02<br />
| No<br />
| No<br />
| 0x01<br />
| 1x<br />
| 268MHz<br />
|-<br />
| 0x05<br />
| Yes<br />
| Yes<br />
| 0x03<br />
| 3x<br />
| 804MHz<br />
|-<br />
| 0x03<br />
| Yes<br />
| No<br />
| 0x02<br />
| 2x<br />
| 536MHz (tested on New3DS)<br />
|}<br />
<br />
Note that the above CFG11_SOCINFO bit is 1 on New3DS, and 0 on Old3DS. Since this SVC is only available with the New3DS ARM11-kernel, the only additional available clock-rate is 804MHz when running on New3DS(with official kernel code).<br />
<br />
The following register value(s) were tested on New3DS by patching the kernel:<br />
* 0x00: Entire system hangs.<br />
* 0x02: Entire system hangs.<br />
* 0x03: ARM11 runs at 536MHz.<br />
* 0x04: Entire system hangs.<br />
* 0x06: Entire system hangs.<br />
* 0x07: Same result as 0x05.<br />
* 0x08: Entire system hangs.<br />
* 0x09: Entire system hangs.<br />
* 0x0A: Entire system hangs.<br />
* 0x0B: Same result as 0x03.<br />
* 0x0C: Entire system hangs.<br />
* 0x0D: Same result as 0x05.<br />
* 0x0E: Entire system hangs.<br />
* 0x0F: Same result as 0x05.<br />
* 0x1F, 0x2F, 0x4F, 0x8F, 0xFF: Same result as 0x05.<br />
<br />
== CFG11_MPCORE_CNT ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| ?<br />
|-<br />
| 8<br />
| ?<br />
|}<br />
<br />
Kernel11 sets this to 0x101 when bit 2 in [[#CFG11_SOCINFO|CFG11_SOCINFO]] is set otherwise 1.<br />
<br />
== CFG11_MPCORE_BOOTCNT<0-3> ==<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Description<br />
|-<br />
| 0<br />
| Enable bootrom instruction overlay, maybe? This bit is only writable for core2 and core3.<br />
|-<br />
| 1<br />
| Enable bootrom data overlay. This bit is only writable for core2 and core3.<br />
|-<br />
| 4<br />
| Has core booted maybe?<br />
|-<br />
| 5<br />
| Always 1?<br />
|}<br />
<br />
The normal ARM11 bootrom checks cpuid and hangs if cpuid >= 2. This is a problem when booting the 2 additional New3DS ARM11 MPCores. NewKernel11 solves this by using a hardware feature to overlay the bootrom with a configurable branch to a kernel function. This overlay feature was added with the New3DS.<br />
<br />
Bit1 in register above enables a bootrom data-override for physical addresses 0xFFFF0000-0xFFFF1000 and 0x10000-0x11000. All _data reads_ made to those regions now read the 32-bit value provided in [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]].<br />
<br />
Bit0 enables a bootrom instruction-overlay which means that _instruction reads_ made to the bootrom region are overridden. We have not been able to dump what instructions are actually placed at bootrom by this switch (because reading the area only yields data-reads). Jumping randomly into the 0xFFFF0000-0xFFFF1000 region works fine and jumps to the value provided by the data overlay [[#CFG11_BOOTROM_OVERLAY_VAL|CFG11_BOOTROM_OVERLAY_VAL]]. Thus we may predict that the entire bootrom region is filled by:<br />
ldr pc, [pc]<br />
<br />
Or equivalent. However, jumping to some high addresses such as 0xFFFF0FF0+ will crash the core. This may be explained by prefetching in the ARM pipeline, and might help us identify what instructions are placed by the instruction-overlay.<br />
<br />
==CFG11_GPUPROT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 3-0<br />
| Old FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: red" | No<br />
| 7-4<br />
| New FCRAM DMA cutoff size, 0 = no protection.<br />
|-<br />
| style="background: green" | Yes<br />
| 8<br />
| AXIWRAM protection, 0 = accessible.<br />
|-<br />
| style="background: red" | No<br />
| 10-9<br />
| QTM DMA cutoff size<br />
|-<br />
| style="background: green" | Yes<br />
| 31-11<br />
| Zeroes<br />
|}<br />
<br />
For the old FCRAM DMA cutoff, it protects starting from 0x28000000-(0x800000*x) until end of FCRAM. There is no way to protect the first 0x800000-bytes.<br />
<br />
For the new FCRAM DMA cutoff, it protects starting from 0x30000000-(0x800000*x) until end of FCRAM. When the old FCRAM cutoff is set to non-zero, the first 0x800000-bytes bytes of new FCRAM are protected.<br />
<br />
On New3DS the old+new FCRAM cutoff can be used at the same time, however this isn't done officially.<br />
<br />
For the QTM DMA cutoff, it protects starting from 0x1F400000-(0x100000*x) until end of QTM mem.<br />
<br />
On cold boot this reg is set to 0.<br />
<br />
When this register is set to value 0, the GPU can access the entire FCRAM, AXIWRAM, and on New3DS all QTM-mem.<br />
<br />
[[SVC|Initialized]] during kernel boot, and used with [[SVC]] 0x59 which was implemented with [[11.3.0-36|v11.3]].<br />
<br />
==CFG11_WIFICNT==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 0<br />
| Enable wifi subsystem<br />
|}<br />
<br />
==CFG11_TWLMODE_0==<br />
Observed 0x8001 when running under TWL_ and AGB_FIRM, 0 NATIVE_FIRM.<br />
<br />
This address is poked from ARM7 to signal that it has booted and begun executing code. The ARM7-mode address for this register is 0x4700000.<br />
<br />
The very last 3DS-mode register poke the [[FIRM|TWL_FIRM]] Process9 does before it gets switched into TWL-mode, is writing 0x8000 to this register. Before writing this register, TWL Process9 waits for ARM7 to change the value of this register. The Process9 code for this runs from ITCM, since switching into TWL-mode includes remapping all ARM9 physical memory.<br />
<br />
Writing 0x8000 to here from the ARM9 with NATIVE_FIRM running doesn't seem to do anything, other reg-pokes likely need done first.<br />
<br />
==CFG11_TWLMODE_1==<br />
Observed 0x8000 when running under TWL_FIRM, 0 NATIVE_FIRM.<br />
<br />
==CFG11_TWLMODE_2==<br />
Bitfield.<br />
<br />
==CFG11_TWLMODE_HID==<br />
The value of this register is copied to [[HID_Registers|HID_?]] under certain conditions.<br />
<br />
==CFG11_WIFIUNK==<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Bits<br />
! Description<br />
|-<br />
| style="background: green" | Yes<br />
| 4<br />
| Wifi-related? Set to 1 very early in NWM-module.<br />
|}<br />
<br />
==CFG11_GPU_CNT==<br />
This one seems to control the LCD/GPU/Backlight.<br />
<br />
Bit0: main (?) nRESET (active low), unset to reset (when not on reset, external GPU registers at 0x10400000+ are enabled).<br />
<br />
Bits 1..6: other nRESET bits.<br />
<br />
Bit16: Enable/Turn on LCD backlight.<br />
<br />
PDN uses a 12 Arm11 cycle delay to deassert reset.<br />
<br />
==CFG11_GPU_CNT2==<br />
Bit0: Power on GPU?<br />
<br />
==CFG11_GPU_FCRAM_CNT==<br />
Bit1: Enable/disable FCRAM.<br />
Bit2: Enable/disable operation in progress.<br />
<br />
==CFG11_CODEC==<br />
The following is the only time the ARM11 CODEC module uses any 0x1EC41XXX registers. In one case CODEC module clears bit1 in register 0x1EC41114, in the other case CODEC module sets bit1 in registers 0x1EC41114 and 0x1EC41116.<br />
<br />
==CFG11_CODEC_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] CODEC service.<br />
<br />
bit0 = unknown, bit1 = turn on/off DSP, rest = always 0.<br />
<br />
==CFG11_CAMERA_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN]] camera service.<br />
<br />
bit0 = unknown, bit1 = turn on/off cameras, rest = always 0.<br />
<br />
==CFG11_DSP_CNT==<br />
This is the power register used for the [[CFG11_Services|PDN Services]] DSP service.<br />
<br />
bit0: NRESET (active low). Unset to reset/hold reset.<br />
bit1: enable bit.<br />
<br />
PDN services holds reset for 0x30 Arm11 cycles.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20952
CONFIG9 Registers
2019-05-07T16:01:05Z
<p>Profi200: /* CFG9_CARDCTL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDMMCCTL|CFG9_SDMMCCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| 1 = Switch to [[SPICARD_Registers|SPICARD]] interface (savegames).<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDMMCCTL ==<br />
CFG9_SDMMCCTL controls power. Also controls SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| SD slot power.<br />
| Process9<br />
|-<br />
| 1<br />
| eMMC power? NAND init hangs if set.<br />
| Process9<br />
|-<br />
|-<br />
| 2-3<br />
| Other power supplies?<br />
| Process9<br />
|-<br />
| 6<br />
| Never used by anything. Set at cold boot.<br />
|<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| If not set force pulls all SD card lines high.<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=I2C_Registers&diff=20933
I2C Registers
2019-04-28T16:12:28Z
<p>Profi200: /* Device 3 */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| I2C1_DATA<br />
| 0x10161000<br />
| 1<br />
| I2C bus 1 devices<br />
|-<br />
| style="background: green" | Yes<br />
| [[#I2C_CNT|I2C1_CNT]]<br />
| 0x10161001<br />
| 1<br />
| I2C bus 1 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C1_CNTEX<br />
| 0x10161002<br />
| 2<br />
| I2C bus 1 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C1_SCL<br />
| 0x10161004<br />
| 2<br />
| I2C bus 1 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C2_DATA<br />
| 0x10144000<br />
| 1<br />
| I2C bus 2 devices<br />
|-<br />
| style="background: green" | Yes<br />
| [[#I2C_CNT|I2C2_CNT]]<br />
| 0x10144001<br />
| 1<br />
| I2C bus 2 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C2_CNTEX<br />
| 0x10144002<br />
| 2<br />
| I2C bus 2 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C2_SCL<br />
| 0x10144004<br />
| 2<br />
| I2C bus 2 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C3_DATA<br />
| 0x10148000<br />
| 1<br />
| I2C bus 3 devices<br />
|-<br />
| style="background: green" | Yes<br />
| [[#I2C_CNT|I2C3_CNT]]<br />
| 0x10148001<br />
| 1<br />
| I2C bus 3 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C3_CNTEX<br />
| 0x10148002<br />
| 2<br />
| I2C bus 3 devices<br />
|-<br />
| style="background: green" | Yes<br />
| I2C3_SCL<br />
| 0x10148004<br />
| 2<br />
| I2C bus 3 devices<br />
|}<br />
<br />
== I2C_CNT ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0<br />
| Stop (0=No, 1=Stop/last byte)<br />
|-<br />
| 1<br />
| Start (0=No, 1=Start/first byte)<br />
|-<br />
| 2<br />
| Pause (0=Transfer Data, 1=Pause after Error, used with/after Stop)<br />
|-<br />
| 4<br />
| Ack Flag (0=Error, 1=Okay) (For DataRead: W, for DataWrite: R)<br />
|-<br />
| 5<br />
| Data Direction (0=Write, 1=Read)<br />
|-<br />
| 6<br />
| Interrupt Enable (0=Disable, 1=Enable)<br />
|-<br />
| 7<br />
| Start/busy (0=Ready, 1=Start/busy)<br />
|}<br />
<br />
== I2C_CNTEX ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-1<br />
| ? Set to 2 normally.<br />
|}<br />
<br />
== I2C_SCL ==<br />
{| class="wikitable" border="1"<br />
! BIT<br />
! DESCRIPTION<br />
|-<br />
| 0-5<br />
| ?<br />
|-<br />
| 8-12<br />
| ? Set to 5 normally.<br />
|}<br />
<br />
= I2C Devices =<br />
{| class="wikitable" border="1"<br />
! [[I2C_Registers|Device id]]<br />
! Device bus id<br />
! Device Write Address<br />
! Accessible via I2C [[I2C_Services|service]]<br />
! Device description<br />
|-<br />
| 0<br />
| 1<br />
| 0x4a<br />
| "i2c::MCU"<br />
| Power management?(same device addr as the DSi power-management)<br />
|-<br />
| 1<br />
| 1<br />
| 0x7a<br />
| "i2c::CAM"<br />
| Camera0?(same dev-addr as DSi cam0)<br />
|-<br />
| 2<br />
| 1<br />
| 0x78<br />
| "i2c::CAM"<br />
| Camera1?(same dev-addr as DSi cam1)<br />
|-<br />
| 3<br />
| 2<br />
| 0x4a<br />
| "i2c::MCU"<br />
| MCU<br />
|-<br />
| 4<br />
| 2<br />
| 0x78<br />
| "i2c::CAM"<br />
| ?<br />
|-<br />
| 5<br />
| 2<br />
| 0x2c<br />
| "i2c::LCD"<br />
| ?<br />
|-<br />
| 6<br />
| 2<br />
| 0x2e<br />
| "i2c::LCD"<br />
| ?<br />
|-<br />
| 7<br />
| 2<br />
| 0x40<br />
| "i2c::DEB"<br />
| ?<br />
|-<br />
| 8<br />
| 2<br />
| 0x44<br />
| "i2c::DEB"<br />
| ?<br />
|-<br />
| 9<br />
| 3<br />
| 0xa6<br />
| "i2c::HID"<br />
| Unknown. The device table in I2C-module had the device address changed from 0xA6 to 0xD6 with [[8.0.0-18]].<br />
|-<br />
| 10<br />
| 3<br />
| 0xd0<br />
| "i2c::HID"<br />
| Gyroscope<br />
|-<br />
| 11<br />
| 3<br />
| 0xd2<br />
| "i2c::HID"<br />
| ?<br />
|-<br />
| 12<br />
| 3<br />
| 0xa4<br />
| "i2c::HID"<br />
| DebugPad<br />
|-<br />
| 13<br />
| 3<br />
| 0x9a<br />
| "i2c::IR"<br />
| IR<br />
|-<br />
| 14<br />
| 3<br />
| 0xa0<br />
| "i2c::EEP"<br />
| eeprom?<br />
|-<br />
| 15<br />
| 2<br />
| 0xee<br />
| "i2c::NFC"<br />
| New3DS-only [[NFC_Services|NFC]]<br />
|-<br />
| 16<br />
| 1<br />
| 0x40<br />
| "i2c::QTM"<br />
| New3DS-only [[QTM_Services|QTM]]<br />
|-<br />
| 17<br />
| 3<br />
| 0x54<br />
| "i2c::IR"<br />
| Used by IR-module starting with [[8.0.0-18]], for New3DS-only HID via "ir:rst". This deviceid doesn't seem to be supported by i2c module on [[8.0.0-18]](actual support was later added in New3DS i2c module).<br />
|}<br />
<br />
'''Notice''': These device addresses are used for writing to the respective device, for reading bit0 must be set (see I2C protocol). Thus, the actual device address is >> 1.<br />
<br />
== Device 3 ==<br />
ro = read-only (writing is no-op)<br />
rw = read-write<br />
wo = write-only (reading will yield 00, FF, or unpredictable data)<br />
<br />
d* = dynamic register (explaination below this table)<br />
s* = shared register (explaination below this table)<br />
ds = dynamic shared (explaination below this table)<br />
{| class="wikitable" border="1"<br />
! REGISTER<br />
! WIDTH<br />
! INFO<br />
! DESCRIPTION <br />
|-<br />
| 0x00<br />
| s<br />
| ro<br />
| Version high<br />
|-<br />
| 0x01<br />
| s<br />
| ro<br />
| Version low<br />
|-<br />
| 0x02<br />
| d<br />
| rw<br />
| 2bit value, writing will mask away/"acknowledge" the event, set to 3 by mcuMainLoop on reset if reset source is Watchdog<br />
bit0: RTC clock value got reset to defaults<br />
bit1: Watchdog reset happened<br />
|-<br />
| 0x03<br />
| ds<br />
| rw<br />
| Top screen flicker<br />
|-<br />
| 0x04<br />
| ds<br />
| rw<br />
| Bottom screen flicker<br />
|-<br />
| 0x05<br />
- 0x07<br />
| s<br />
| rw<br />
| Danger zone - [[MCU_Services#MCU_firmware_versions|MCU unlock sequence]] is written here.<br />
|-<br />
| 0x08<br />
| s<br />
| ro<br />
| Raw 3D slider position<br />
|-<br />
| 0x09<br />
| s<br />
| ro<br />
| Volume slider state (0x00 - 0x3F)<br />
This is the same value returned by [[MCUHWC:GetSoundVolume|MCUHWC:GetSoundVolume]]<br />
|-<br />
| 0x0A<br />
| s<br />
| ro<br />
| ? (seems to be power management related?)<br />
|-<br />
| 0x0B<br />
| s<br />
| ro<br />
| Battery percentage<br />
|-<br />
| 0x0C<br />
| s<br />
| ro<br />
| ? (changes to 0 for a second when the charger is plugged in then it resets to its previous value)<br />
|-<br />
| 0x0D<br />
| s<br />
| ro<br />
| System voltage<br />
|-<br />
| 0x0E<br />
| s<br />
| ro<br />
| ?<br />
|-<br />
| 0x0F<br />
| s<br />
| ro<br />
| Flags: bit7-5 are read via [[MCU_Services|mcu::GPU]]. The rest of these are read via [[MCU_Services|mcu::RTC]]: bit4 = BatteryChargeState. bit3 = AdapterState. bit1 = ShellState.<br />
|-<br />
| 0x10<br />
- 0x13<br />
| s<br />
| ro<br />
| Received interrupt bitmask, see register 0x18 for possible values <br />
If no interrupt was received this register is 0<br />
|-<br />
| 0x14<br />
| s<br />
| ro<br />
| Unused and unwritable byte :(<br />
|-<br />
| 0x15<br />
- 0x17<br />
| s<br />
| rw<br />
| Unused and unreferenced free RAM! Good for userdata.<br />
|-<br />
| 0x18<br />
- 0x1B<br />
| s<br />
| rw<br />
| Interrupt mask for register 0x10 (0=enabled,1=disabled)<br />
bit00: Power button press (for 27 "ticks")<br />
bit01: Power button held (for 375 "ticks"; the 3DS turns off regardless after a fixed time)<br />
bit02: HOME button press (for 5 "ticks")<br />
bit03: HOME button release<br />
bit04: WiFi switch button<br />
bit05: Shell close<br />
bit06: Shell open<br />
bit07: Fatal hardware condition([[Services#Notifications|?]]) (sent when the MCU gets reset by the Watchdog timer)<br />
bit08: Charger removed<br />
bit09: Charger plugged in<br />
bit10: RTC alarm (when some conditions are met it's sent when the current day and month and year matches the current RTC time)<br />
bit11: ??? (accelerometer related)<br />
bit12: HID update<br />
bit13: Battery dead(?)<br />
bit14: Battery stopped charging (independent of charger state)<br />
bit15: Battery started charging<br />
Nonmaskable(?) interrupts<br />
bit16: ???<br />
bit17: ??? (opposite even for bit16)<br />
bit22: Volume slider position change<br />
bit23: ??? Register 0x0E update<br />
bit24: ??? (the off event for below bit)<br />
bit25: ??? (triggered when something related to the GPU is turned on)<br />
bit26: ??? (???)<br />
bit27: ??? (???)<br />
bit28: ??? (???)<br />
bit29: Battery percentage status change (triggered at 10%, 5%, and 0% while discharging)<br />
bit30: bit set by mcu sysmodule<br />
bit31: bit set by mcu sysmodule<br />
|-<br />
| 0x1C<br />
- 0x1F<br />
| s<br />
| rw<br />
| Unused and unreferenced free RAM! Good for userdata.<br />
|-<br />
| 0x20<br />
| d<br />
| wo<br />
| System power control:<br />
bit0: power off<br />
bit1: reboot (unused?)<br />
bit2: reboot (used by mcu sysmodule and LgyBg)<br />
bit3: used by LgyBg to power off, causes hangs in 3DS-mode<br />
bit4: an mcu::RTC command uses this, seems to do something with the watchdog<br />
Bit 4 sets a bit at a RAM address which seems to control the watcdog timer state, then this bit is immediately unmasked. This field has a bitmask of 0x0F. <br />
|-<br />
| 0x21<br />
| d<br />
| wo<br />
| ??? switches up input bits from <code>0123456--</code> to <code>12-0435-</code> then writes them to REG[0x5D] (<code>0xFFC02</code>)<br />
|-<br />
| 0x22<br />
| d<br />
| wo<br />
| Used to set LCD states<br />
bit0: don't push to LCDs<br />
bit1: push to LCDs<br />
bit2: bottom screen backlight off<br />
bit3: bottom screen backlight on<br />
bit4: top screen backlight off<br />
bit5: top screen backlight on<br />
<br />
Bits 4 and 5 have no effect on a 2DS because the backlight source is the bottom screen.<br />
The rest of the bits are masked away.<br />
|-<br />
| 0x23<br />
| ??<br />
| wo<br />
| ??? Seems to be stubbed, just returns the written value from the write handler function.<br />
|-<br />
| 0x24<br />
| s<br />
| rw<br />
| Watchdog timer. This must be set *before* the timer is triggered, otherwise the old value is used. Value zero disables the watchdog.<br />
|-<br />
| 0x25<br />
| s<br />
| rw<br />
| ?<br />
|-<br />
| 0x26<br />
| s<br />
| rw<br />
| ?<br />
|-<br />
| 0x27<br />
| sd<br />
| rw<br />
| Raw volume slider state<br />
|-<br />
| 0x28<br />
| s<br />
| rw<br />
| Brightness of the WiFi/Power LED<br />
|-<br />
| 0x29<br />
| sd(5)<br />
| rw<br />
| Power LED state + some extra data<br />
|-<br />
| 0x2A<br />
| s<br />
| rw<br />
| WiFi LED state, non-0 value turns on the WiFi LED, 4 bits wide<br />
|-<br />
| 0x2B<br />
| s<br />
| rw<br />
| Camera LED state, 4bits wide,<br />
0, 3, 6-0xF = off<br />
1 = slowly blinking<br />
2 = constantly on<br />
4 = flash once<br />
5 = delay before changing to 2<br />
|-<br />
| 0x2C<br />
| s<br />
| rw<br />
| 3D LED state, 4 bits wide<br />
|-<br />
| 0x2D<br />
| 0x64<br />
| wo<br />
| This is used for [[MCURTC:SetInfoLEDPattern|controlling]] the notification LED (see [[MCURTC:SetInfoLEDPatternHeader]] as well), when this register is written. It's possible to write data here with size less than 0x64, and only that portion of the pattern data will get overwritten. Reading from this register only returns zeroes, so it's considered write-only. Writing past the size of this register seems to do nothing.<br />
|-<br />
| 0x2E<br />
| s<br />
| ro<br />
| This [[MCURTC:GetInfoLEDStatus|returns]] the notification LED status when read (1 means new cycle started)<br />
|-<br />
| 0x2F<br />
| s<br />
| wo?<br />
| ??? The write function for this register is stubbed.<br />
|-<br />
| 0x30<br />
- 0x36<br />
| ds<br />
| rw<br />
| RTC time (system clock). 7 bytes are read from this. The upper nibble of each byte encodes 10s (BCD), so each byte is post-processed with (byte & 0xF) + (10 * (byte >> 4)).<br />
byte 0: seconds<br />
byte 1: minutes<br />
byte 2: hours<br />
byte 3: current week (unused)<br />
byte 4: days<br />
byte 5: months<br />
byte 6: years<br />
|-<br />
| 0x37<br />
| s<br />
| rw<br />
| RTC time byte 7: leap year counter / "watch error correction" register (unused in code)<br />
|-<br />
| 0x38<br />
- 0x3C<br />
| s<br />
| rw<br />
| RTC alarm registers<br />
byte 0: minutes(???)<br />
byte 1: hours(???)<br />
byte 2: day<br />
byte 3: month<br />
byte 4: year<br />
|-<br />
| 0x3B<br />
| s<br />
| rw<br />
| Could be used on very old MCU_FIRM versions to upload [[MCU_Services#MCU_firmware_versions|MCU firmware]] if some conditions are met.<br />
|-<br />
| 0x3D<br />
0x3E<br />
| ds<br />
| ro<br />
| RTC tick counter / "ITMC" (when resets to 0 the seconds increase)<br />
Only reading 0x3D will update the in-RAM value<br />
|-<br />
| 0x3F<br />
| s<br />
| wo<br />
| 2 bits<br />
bit0: turns off P00 and sets it to output mode (seems to kill the entire SoC)<br />
bit1: turns on a prohibited bit in an RTC Control register and turns P12 into an output<br />
|-<br />
| 0x40<br />
| s<br />
| rw<br />
| Pedometer state (?)<br />
|-<br />
| 0x41<br />
| s<br />
| rw<br />
| Index selector for register 0x44<br />
|-<br />
| 0x42<br />
| s<br />
| rw<br />
| Unused?<br />
|-<br />
| 0x43<br />
| s<br />
| rw<br />
| Unused???, accelometer related<br />
|-<br />
| 0x44<br />
| s<br />
| rw<br />
| ???, accelometer related<br />
|-<br />
| 0x45<br />
- 0x4A<br />
| s<br />
| ro<br />
| Gyroscope 3D rotation from the 12bit ADC, left shifted 4 to fit in a 16bit signed short<br />
{| class="wikitable" border="1"<br />
! AXIS<br />
! V=0x00<br />
! V=0x40<br />
! V=0xC0 <br />
|-<br />
| Y (=roll)<br />
| held vertically<br />
| vertical right side<br />
| vertical left side<br />
|-<br />
| Z? (=yaw)<br />
| ???<br />
| ???<br />
| ???<br />
|-<br />
| X? (=pitch)<br />
| held vertically<br />
| ???<br />
| ???<br />
|}<br />
|-<br />
| 0x4B<br />
| s<br />
| rw<br />
| PedometerStepCount (for the current day)<br />
|-<br />
| 0x4C<br />
0x4D<br />
| ??<br />
| ??<br />
| ??<br />
|-<br />
| 0x4E<br />
| d<br />
| rw<br />
| ??? this = (0xFFE9E & 1) ? 0x10 : 0<br />
|-<br />
| 0x4F<br />
| d(6)<br />
| ro<br />
| <br />
|-<br />
| 0x50<br />
| s<br />
| rw<br />
| ???<br />
|-<br />
| 0x51<br />
| s<br />
| rw<br />
| ???<br />
|-<br />
| 0x52<br />
- 0x57<br />
| s<br />
| rw<br />
| ?<br />
|-<br />
| 0x58<br />
| s<br />
| rw<br />
| Register-mapped ADC register<br />
DSP volume slider 0% volume offset (setting this to 0xFF will esentially mute the DSP as it's the volume slider's maximum raw value)<br />
|-<br />
| 0x59<br />
| s<br />
| rw<br />
| Register-mapped ADC register<br />
DSP volume slider 100% volume offset (setting both this and the above to 0 will disable the volume slider with 100% volume, setting this to a lower value than the above will make the volume slider have only 2 states; on and off)<br />
|-<br />
| 0x5A<br />
| s<br />
| ro/rw<br />
| Invalid, do not use! On newer MCU_FIRM versions this is unused, but on older MCU_FIRM versions this is a read-only counter.<br />
|-<br />
| 0x5B<br />
- 0x5F<br />
| s<br />
| - <br />
| These registers are out of bounds (0xFFC00 and up), they don't exist, writing is no-op, reading will yield FFs.<br />
|-<br />
| 0x60<br />
| ds<br />
| rw<br />
| Looping queue register<br />
Writing to first byte resets the queue position to the nth element<br />
Reading from this register causes the values to shift up by `readsize-1`(needs confirmation) bytes after returning `readsize-1` bytes from the top of the stack (first byte is read-only, so is always zero)<br />
|-<br />
| 0x61<br />
| ds(0x100)<br />
| rw<br />
| Writing to this register pushes values on top of register 0x60's stack. Reading from this register doesn't advance the stack.<br />
The first byte is used to store flags for managing FIRM/NS state - bit0 = "WirelessDisabled", bit1 = "SoftwareClosed", bit2 = "PowerOffInitiated", bit4 = "LegacyJumpProhibited". This register survives a power-off, but it resides in RAM, so its contents get lost on battery pulls. This register doesn't seem to actually control MCU behaviour by itself, it just seems to be used for storing arbitrary data.<br />
|-<br />
| 0x62 - 0x7E<br />
| s<br />
| -<br />
| These registers don't exist, writing is no-op, reading will yield FFs.<br />
|-<br />
| 0x7F<br />
| d(9-0x13)<br />
| ro<br />
| Various system state information.<br />
byte 0x06: battery related? (seems to decrease while charging and increase while discharging)<br />
byte 0x09: system model (see [[Cfg:GetSystemModel#System_Model_Values|Cfg:GetSystemModel]] for values)<br />
byte 0x0A: power LED related? 0 is off, 1 is red<br />
byte 0x0D: RGB LED red intensity<br />
byte 0x0E: RGB LED green intensity<br />
byte 0x0F: RGB LED blue intensity<br />
byte 0x11: WiFi LED brightness<br />
byte 0x12: raw button states?<br />
bit0: unset while power button is held<br />
bit1: unset while home button is held<br />
bit2: unset while Wifi slider is held<br />
bit5: unset while the charging LED is active<br />
bit6: unset while charger is plugged in<br />
<br />
this byte is reset to 0 before an svcBreak takes effect<br />
<br />
On MCU_FIRM major version 1 the size of this is 9, reading past the 9th byte will yield AA instead of FF.<br />
|-<br />
| 0x80<br />
- 0xFF<br />
| s<br />
| -<br />
| These registers don't exist, writing is no-op, reading will yield FFs.<br />
|}<br />
<br />
Shared register: the letter "s" means that the given register is in a "shared register pool", meaning the resgister is in the register pool in RAM at address <code>0xFFBA4 + registernumber</code>.<br />
<br />
Dynamic register: these registers aren't in the shared pool, they just "pretend" to be there. These registers often don't retain their set value, change rapidly, or control various hardware.<br />
<br />
Non-shared (dynamic) register: it's a register whose contents separate from the shared register pool. Messing with these registers will not affect the shared register pool at all.<br />
<br />
On old versions of MCU_FIRM none of the invalid registers are masked away by the read handler function, but are still read-only. Newer MCU_FIRM versions return the hardcoded value FF instead.<br />
<br />
== Device 5 & 6 ==<br />
LCD controllers for main/sub displays, most likely.<br />
<br />
{| class="wikitable" border="1"<br />
! Register<br />
! Width<br />
! Name<br />
! Description<br />
|-<br />
| 0x1<br />
| 8<br />
| ?<br />
| <br />
|-<br />
| 0x11<br />
| 8<br />
| ?<br />
| <br />
|-<br />
| 0x40<br />
| 8<br />
| CMD_IN/CMD_RESULT1<br />
| Write to trigger a command? Seen commands: 0xFF=Reset?, 0x62=IsFinished?. Result is stored in CMD_RESULT1:CMD_RESULT0.<br />
|-<br />
| 0x41<br />
| 8<br />
| CMD_RESULT0<br />
| Read result <br />
|-<br />
| 0x50<br />
| 8<br />
| ?<br />
| <br />
|-<br />
| 0x60<br />
| 8<br />
| ?<br />
| <br />
|-<br />
| 0xFE<br />
| 8<br />
| ?<br />
| <br />
|}<br />
<br />
== Device 10 ==<br />
See the datasheet linked to on the [[Hardware]] page for reference.<br />
<br />
== Device 12 ==<br />
{| class="wikitable" border="1"<br />
! REGISTER<br />
! WIDTH<br />
! DESCRIPTION <br />
|-<br />
| 0x0<br />
| 21<br />
| DebugPad state.<br />
|}<br />
<br />
This is the DebugPad device, see [[HID_Shared_Memory|here]].<br />
<br />
== Device 13 ==<br />
{| class="wikitable" border="1"<br />
! Raw I2C register address<br />
! Internal register address<br />
! Width<br />
! Description <br />
|-<br />
| 0x0<br />
| 0x0<br />
| 0x40<br />
| RHR / THR (data receive/send FIFO)<br />
|-<br />
| 0x8<br />
| 0x1<br />
| 0x1<br />
| IER<br />
|-<br />
| 0x10<br />
| 0x2<br />
| 0x1<br />
| FCR/IIR<br />
|-<br />
| 0x18<br />
| 0x3<br />
| 0x1<br />
| LCR<br />
|-<br />
| 0x20<br />
| 0x4<br />
| 0x1<br />
| MCR<br />
|-<br />
| 0x28<br />
| 0x5<br />
| 0x1<br />
| LSR<br />
|-<br />
| 0x30<br />
| 0x6<br />
| 0x1<br />
| MSR/TCR<br />
|-<br />
| 0x38<br />
| 0x7<br />
| 0x1<br />
| SPR/TLR<br />
|-<br />
| 0x40<br />
| 0x8<br />
| 0x1<br />
| TXLVL<br />
|-<br />
| 0x48<br />
| 0x9<br />
| 0x1<br />
| RXLVL<br />
|-<br />
| 0x50<br />
| 0xA<br />
| 0x1<br />
| IODir<br />
|-<br />
| 0x58<br />
| 0xB<br />
| 0x1<br />
| IOState<br />
|-<br />
| 0x60<br />
| 0xC<br />
| 0x1<br />
| IoIntEna<br />
|-<br />
| 0x68<br />
| 0xD<br />
| 0x1<br />
| reserved<br />
|-<br />
| 0x70<br />
| 0xE<br />
| 0x1<br />
| IOControl<br />
|-<br />
| 0x78<br />
| 0xF<br />
| 0x1<br />
| EFCR<br />
|}<br />
<br />
See the [http://www.alldatasheet.net/datasheet-pdf/pdf/347838/NXP/SC16IS750IBS.html datasheet] linked to on the [[Hardware]] page for reference. From that datasheet, for the structure of the I2C register address u8: "Bit 0 is not used, bits 2:1 select the channel, bits 6:3 select one of the UART internal registers. Bit 7 is not used with the I2C-bus interface, but it is used by the SPI interface to indicate a read or a write operation."<br />
<br />
== Device 14 ==<br />
<br />
Used by [[Config_Services|Cfg]]-sysmodule via the i2c::EEP service. This is presumably EEPROM going by the service name.<br />
<br />
The Cfg-module code which loads the [[Flash_Filesystem|CCAL]](nandro:/sys/{HWCAL0.dat/HWCAL1.dat}) file from NAND will load it from I2C instead, if a certain state flag is non-zero. Likewise for the function which writes CCAL to NAND. HMAC/hash verification after loading is skipped when the CCAL was loaded from I2C.<br />
<br />
== Device 15 ==<br />
This the New3DS [[NFC_Services|NFC]] controller "I2C" interface. This device is accessed via the WriteDeviceRaw/ReadDeviceRaw I2C service [[I2C_Services|commands]].<br />
<br />
Since the *Raw commands are used with this, this device has no I2C registers. Instead, raw data is transfered after the I2C device is selected. Hence, WriteDeviceRaw is used for sending commands to the controller, while ReadDeviceRaw is for receiving responses from the controller. Certain commands may return multiple command responses.<br />
<br />
Command request / response structure:<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x1<br />
| Normally 0x10?<br />
|-<br />
| 0x1<br />
| 0x1<br />
| Command source / destination.<br />
|-<br />
| 0x2<br />
| 0x1<br />
| CmdID<br />
|-<br />
| 0x3<br />
| 0x1<br />
| Payload size.<br />
|}<br />
<br />
Following the above header is the payload data(when payload size is non-zero), with the size specified in the header. The command response payload is usually at least 1-byte, where that byte appears to be normally 0x0. For command requests the payload data is the command parameters.<br />
<br />
For command requests sent to the NFC tag itself, Cmd[1]=0x0 and CmdID=0x0. The command request payload data here is the actual command request data for the NFC tag, starting with the CmdID u8 at payload+0.<br />
<br />
During NFC module startup, a certain command is sent to the controller which eventually(after various cmd-reply headers etc) returns the following the payload after the first byte in the payload:<br />
000000: 44 65 63 20 32 32 20 32 30 31 32 31 34 3a 35 33 Dec 22 201214:53 <br />
000010: 3a 35 30 01 05 0d 46 05 1b 79 20 07 32 30 37 39 :50...F..y .2079<br />
000020: 31 42 35 1B5<br />
<br />
Or that is: "Dec 22 201214:53:50<binary>20791B5". Therefore, this appears to return the part-number of the NFC controller(other command request(s) / response(s) use this part-number value too).<br />
<br />
=== NFC controller commands ===<br />
{| class="wikitable" border="1"<br />
! CmdRequest[1]<br />
! CmdID<br />
! Payload data for parameters<br />
! Description<br />
|-<br />
| 0x2E<br />
| 0x2F<br />
| Firmware image for this chunk, size varies.<br />
| This is used during NFC module startup to upload the firmware image to the NFC controller. This is used repeatedly to upload multiple chunks of the image.<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20931
SPI Registers
2019-04-20T19:54:26Z
<p>Profi200: /* SPI_NEW_STATUS */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
This register reads as 1 after starting a transfer. When the transfer is finished, a 0 has to be written to this register. This is probaly the Chip Select line.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy. At transfer start and every 32 bytes the FIFO becomes busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20930
SPI Registers
2019-04-20T19:52:00Z
<p>Profi200: /* SPI_NEW_DONE */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
This register reads as 1 after starting a transfer. When the transfer is finished, a 0 has to be written to this register. This is probaly the Chip Select line.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=SPI_Registers&diff=20929
SPI Registers
2019-04-20T19:48:10Z
<p>Profi200: /* SPI_NEW_CNT */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]0<br />
| 0x10142000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA0<br />
| 0x10142002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]0<br />
| 0x10142800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]0<br />
| 0x10142804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]0<br />
| 0x10142808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]0<br />
| 0x1014280C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]0<br />
| 0x10142810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]1<br />
| 0x10143000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA1<br />
| 0x10143002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]1<br />
| 0x10143800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]1<br />
| 0x10143804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]1<br />
| 0x10143808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]1<br />
| 0x1014380C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]1<br />
| 0x10143810<br />
| 4<br />
|<br />
|-style="border-top: double"<br />
| style="background: green" | Yes<br />
| [[#SPI_CNT|SPI_CNT]]2<br />
| 0x10160000<br />
| 2<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| SPI_DATA2<br />
| 0x10160002<br />
| 1 <br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_CNT|SPI_NEW_CNT]]2<br />
| 0x10160800<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_DONE|SPI_NEW_DONE]]2<br />
| 0x10160804<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_BLKLEN|SPI_NEW_BLKLEN]]2<br />
| 0x10160808<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_FIFO|SPI_NEW_FIFO]]2<br />
| 0x1016080C<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#SPI_NEW_STATUS|SPI_NEW_STATUS]]2<br />
| 0x10160810<br />
| 4<br />
|<br />
|}<br />
<br />
There are two register interfaces: the old NDS/DSi one and an alternative faster interface introduced with the 3DS.<br />
<br />
To toggle between those interfaces, use the [[CONFIG11_Registers#CFG11_SPI_CNT|CFG11_SPI_CNT]] register.<br />
<br />
== SPI_CNT ==<br />
This is the old NDS/DSi SPI interface.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-1<br />
| Baudrate (0=4MHz, 1=2MHz, 2=1MHz, 3=512KHz)<br />
|-<br />
| 2-6<br />
| This was added with 3DS.<br />
|-<br />
| 7<br />
| Busy Flag (0=Ready, 1=Busy) (presumably Read-only)<br />
|- <br />
| 8-9<br />
| Device Select (0=Powerman., 1=Firmware, 2=Touchscreen)<br />
|-<br />
| 10<br />
| Transfer Size (0=8bit/Normal, 1=16bit/Bugged)<br />
|-<br />
| 11<br />
| Chipselect Hold (0=Deselect after transfer, 1=Keep selected)<br />
|-<br />
| 12-13<br />
| Not used (Zero)<br />
|-<br />
| 14<br />
| Interrupt Request (0=Disable, 1=Enable)<br />
|-<br />
| 15<br />
| SPI Bus Enable (0=Disable, 1=Enable)<br />
|}<br />
<br />
== SPI_NEW_CNT ==<br />
This is an alternative faster interface introduced with the 3DS.<br />
<br />
{| class="wikitable" border="1"<br />
! Bits<br />
! Name<br />
|-<br />
| 0-2<br />
| Baudrate?<br />
|-<br />
| 6-7<br />
| Device Select<br />
|-<br />
| 12<br />
| ?<br />
|-<br />
| 13<br />
| Transfer Direction? (0=Incoming, 1=Outgoing)<br />
|-<br />
| 15<br />
| Busy/enable<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Device select bits<br />
|-<br />
| 0, 3, >=6<br />
| 0<br />
|-<br />
| 1, 4<br />
| 1<br />
|-<br />
| 2, 5<br />
| 2<br />
|}<br />
<br />
{| class="wikitable" border="1"<br />
! Device id<br />
! Used baudrate<br />
|-<br />
| 3<br />
| 5<br />
|-<br />
| 0<br />
| 2<br />
|}<br />
<br />
== SPI_NEW_DONE ==<br />
When the transfer is finished, a 0 has to be written to this register.<br />
<br />
==SPI_NEW_BLKLEN==<br />
The number of bytes to be sent/read is written to this register.<br />
<br />
==SPI_NEW_FIFO==<br />
32-bit FIFO for reading/writing the SPI payload.<br />
<br />
==SPI_NEW_STATUS==<br />
Bit0: FIFO busy.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=ARM11_Interrupts&diff=20928
ARM11 Interrupts
2019-04-20T14:47:09Z
<p>Profi200: /* Hardware Interrupts */</p>
<hr />
<div>== Interrupts ==<br />
<br />
Interrupt priority is 0-0xF. A priority of 0xF means that the interrupt is disabled.<br />
<br />
= Private Interrupts =<br />
<br />
Each CPU core has 32 software interrupts that are private and belong to that core. These interrupts are numbers 0-0x1F for each core. The hardware interrupts are not core-specific and start at interrupt ID 0x20.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0<br />
| <br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0x1<br />
| <br />
| MPCore software-interrupt. Used by BOOT11 to kickstart Core1.<br />
|-<br />
| 0x2-0x3<br />
| <br />
| MPCore software-interrupt. Seem to be unused.<br />
|-<br />
| 0x4<br />
| Kernel<br />
| MPCore software-interrupt. Used to manage the performance counter.<br />
|-<br />
| 0x5<br />
| Kernel<br />
| MPCore software-interrupt. Does apparently nothing.<br />
|-<br />
| 0x6<br />
| Kernel<br />
| MPCore software-interrupt. Extensively used by [[SVC|KernelSetState]] (and contains most of the actual code of the latter).<br />
|-<br />
| 0x7<br />
| Kernel<br />
| MPCore software-interrupt. See [[KCacheMaintenanceInterruptEvent]]<br />
|-<br />
| 0x8<br />
| Kernel<br />
| MPCore software-interrupt. Used for scheduling.<br />
|-<br />
| 0x9<br />
| Kernel<br />
| MPCore software-interrupt. Used when handling exceptions that require termination of a thread or a process, and in some cases by svcSetDebugThreadContext, to store VFP registers in the thread's register storage.<br />
|-<br />
| 0xA<br />
| Kernel<br />
| TLB operations interrupt, see [[KTLBOperationsInterruptEvent]]<br />
|-<br />
| 0xB-0xE<br />
|<br />
| MPCore software-interrupt. Not configured.<br />
|-<br />
| 0xF<br />
| dmnt/debugger<br />
| MPCore software-interrupt. Used to abstract FIQ (debug). This interrupt is never sent to core2 nor core3 on N3DS.<br />
|-<br />
| 0x1D<br />
| Kernel<br />
| MPCore timer.<br />
|-<br />
| 0x1E<br />
| Kernel<br />
| MPCore watchdog - set when the watchdog counter reaches 0 in timer mode, causes interrupt 30 to set as pending. Only set on core 1 as core 1's timer is used for everything.<br />
|}<br />
<br />
= Hardware Interrupts =<br />
<br />
There are 0x60 hardware interrupts starting at 0x20 and continuing up to 0x7F. These are not private and are accessible from any core.<br />
<br />
{| class="wikitable" border="1"<br />
! IRQ<br />
! Listener<br />
! Description<br />
|-<br />
| 0x28<br />
| gsp, TwlBg<br />
| PSC0<br />
|-<br />
| 0x29<br />
| gsp, TwlBg<br />
| PSC1<br />
|-<br />
| 0x2A<br />
| gsp, TwlBg<br />
| PDC0 (VBlank0)<br />
|-<br />
| 0x2B<br />
| gsp, TwlBg<br />
| PDC1 (VBlank1)<br />
|-<br />
| 0x2C<br />
| gsp, TwlBg<br />
| PPF<br />
|-<br />
| 0x2D<br />
| gsp, TwlBg<br />
| P3D<br />
|-<br />
| 0x30<br />
| Kernel<br />
| ?<br />
|-<br />
| 0x39<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3A<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x3B<br />
| Kernel<br />
| DMA<br />
|-<br />
| 0x40<br />
| nwm<br />
| WIFI SDIO Controller @ 0x10122000<br />
|-<br />
| 0x41<br />
| nwm<br />
| ?<br />
|-<br />
| 0x42<br />
| nwm_dev?<br />
| WIFI SDIO Controller @ 0x10100000<br />
|-<br />
| 0x45<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x46<br />
| mvd (New3DS)<br />
| ?<br />
|-<br />
| 0x48<br />
| camera<br />
| ?<br />
|-<br />
| 0x49<br />
| camera<br />
| ?<br />
|-<br />
| 0x4A<br />
| dsp<br />
| ?<br />
|-<br />
| 0x4B<br />
| camera<br />
| Y2R Conversion Finished<br />
|-<br />
| 0x4C<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4D<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x4E<br />
| mvd (New3DS)<br />
| Y2R2 End Event<br />
|-<br />
| 0x4F<br />
| mvd (New3DS)<br />
| Related to mvd services<br />
|-<br />
| 0x50<br />
| pxi, TwlBg<br />
| Sync<br />
|-<br />
| 0x51<br />
| pxi, TwlBg<br />
| ?<br />
|-<br />
| 0x52<br />
| pxi, TwlBg<br />
| Send Fifo Empty<br />
|-<br />
| 0x53<br />
| pxi, TwlBg<br />
| Receive Fifo Not Empty<br />
|-<br />
| 0x54<br />
| i2c, TwlBg<br />
| I2C Bus0 work done<br />
|-<br />
| 0x55<br />
| i2c, TwlBg<br />
| I2C Bus1 work done<br />
|-<br />
| 0x56<br />
| spi, TwlBg<br />
| ?<br />
|-<br />
| 0x57<br />
| spi, TwlBg<br />
| SPI bus 0 transfer finished?<br />
|-<br />
| 0x58<br />
| Kernel<br />
| PDN<br />
|-<br />
| 0x59<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x5A<br />
| mic<br />
| ?<br />
|-<br />
| 0x5C<br />
| i2c, TwlBg<br />
| I2C Bus2 work done<br />
|-<br />
| 0x60<br />
| gpio, TwlBg<br />
| Shell opened<br />
|-<br />
| 0x62<br />
| gpio, TwlBg<br />
| Shell closed<br />
|-<br />
| 0x63<br />
| gpio, TwlBg<br />
| Touchscreen<br />
|-<br />
| 0x64<br />
| gpio, TwlBg<br />
| Headphone jack plugged in/out<br />
|-<br />
| 0x66<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x68<br />
| gpio, TwlBg<br />
| IR<br />
|-<br />
| 0x69<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6A<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6B<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6C<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6D<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6E<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x6F<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x70<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x71<br />
| gpio, TwlBg<br />
| MCU (HOME/POWER pressed/released or WiFi switch pressed)<br />
|-<br />
| 0x72<br />
| gpio, TwlBg<br />
| ?<br />
|-<br />
| 0x73<br />
| TwlBg<br />
| ?<br />
|-<br />
| 0x74<br />
| ?<br />
| Gamecard related<br />
|-<br />
| 0x75<br />
| ?<br />
| Gamecard inserted<br />
|-<br />
| 0x78 to 0x7B<br />
| Kernel<br />
| Core 0-3 Performance monitor counter (any) overflow<br />
|-<br />
| 0x7A to 0x82 (PDN_MPCORE_CFG bit2 set) or<br />
0x7C to 0x84 (bit2 clear)<br />
| Kernel<br />
| ?<br />
|}<br />
(interrupts from 0x80 and up can't be mapped in available builds of the kernel)<br />
<br />
<br />
There are 2 tables in the ARM11 kernel: the first has 32 * 2(or 32 * 4) 8-byte entries. This table is for the private interrupts that belong to each core. The data for each interrupt can be found by doing table_base + (core_num * 0x100) + (intr_num * 8). The second table is for public hardware interrupts and the data for each interrupt can be retrieved by doing table_base + (intr_num * 8).<br />
<br />
= InterruptData =<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| [[KBaseInterruptEvent]] *<br />
| Pointer to the KBaseInterruptEvent object for this interrupt <br />
|-<br />
| 0x4<br />
| u8<br />
| Interrupt will be disabled by the IRQ handler as soon as it is acknowledged.<br />
Ignored for FIQ: the FIQ handler always sets bit2 of [[PDN_Registers#PDN_FIQ_CNT|PDN_FIQ_CNT]]<br />
|-<br />
| 0x5<br />
| u8<br />
| Interrupt is disabled<br />
|-<br />
| 0x6<br />
| u8<br />
| Interrupt priority<br />
|-<br />
| 0x7<br />
| u8<br />
| Unused, alignment<br />
|}<br />
<br />
= Interrupt Table (New3DS) =<br />
(0xFFF318F4 in 10.3)<br />
<br />
{| class="wikitable" border="1"<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| InterruptData[224]<br />
| Data for all hardware and software interrupts<br />
|-<br />
| 0x700<br />
| [[KObjectMutex]]<br />
| Mutex<br />
|}</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20705
CONFIG9 Registers
2018-05-29T18:10:59Z
<p>Profi200: /* CFG9_SDMMCCTL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDMMCCTL|CFG9_SDMMCCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| Enable gamecard eject IRQ, maybe?<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDMMCCTL ==<br />
CFG9_SDMMCCTL controls power. Also controls SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| SD slot power.<br />
| Process9<br />
|-<br />
| 1<br />
| eMMC power? NAND init hangs if set.<br />
| Process9<br />
|-<br />
|-<br />
| 2-3<br />
| Other power supplies?<br />
| Process9<br />
|-<br />
| 6<br />
| Never used by anything. Set at cold boot.<br />
|<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| If not set force pulls all SD card lines high.<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20704
CONFIG9 Registers
2018-05-29T17:40:26Z
<p>Profi200: </p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDMMCCTL|CFG9_SDMMCCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| Enable gamecard eject IRQ, maybe?<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDMMCCTL ==<br />
CFG9_SDMMCCTL controls power. Also controls SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| SD slot power.<br />
| Process9<br />
|-<br />
| 1<br />
| eMMC power? NAND init hangs if set.<br />
| Process9<br />
|-<br />
|-<br />
| 2-3<br />
| Other power supplies?<br />
| Process9<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| If not set force pulls all SD card lines high.<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20703
CONFIG9 Registers
2018-05-28T18:02:52Z
<p>Profi200: /* CFG9_SDSLOTCTL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDSLOTCTL|CFG9_SDSLOTCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| Enable gamecard eject IRQ, maybe?<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDSLOTCTL ==<br />
CFG9_SDSLOTCTL controls power and SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0-3<br />
| Bit 0 powers on the SD card slot when unset. Bit 2 set = the 3DS hangs somewhere after successful SD init. Remaining unknown.<br />
| Process9<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| If not set force pulls all SD card lines high.<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20702
CONFIG9 Registers
2018-05-28T16:25:24Z
<p>Profi200: /* CFG9_SDSLOTCTL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDSLOTCTL|CFG9_SDSLOTCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| Enable gamecard eject IRQ, maybe?<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDSLOTCTL ==<br />
CFG9_SDSLOTCTL controls power and SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0-3<br />
| Bit 0 powers on the SD card slot when unset. If bit 2 is set the 3DS hangs somewhere after successful SD init.<br />
| Process9<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| If not set force pulls all SD card lines high.<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200
https://www.3dbrew.org/w/index.php?title=CONFIG9_Registers&diff=20701
CONFIG9 Registers
2018-05-28T16:10:39Z
<p>Profi200: /* CFG9_SDSLOTCTL */</p>
<hr />
<div>= Registers =<br />
{| class="wikitable" border="1"<br />
! Old3DS<br />
! Name<br />
! Address<br />
! Width<br />
! Used by<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT9|CFG9_SYSPROT9]]<br />
| 0x10000000<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SYSPROT11|CFG9_SYSPROT11]]<br />
| 0x10000001<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_RST11|CFG9_RST11]]<br />
| 0x10000002<br />
| 1<br />
| Boot9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_DEBUGCTL<br />
| 0x10000004<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000008<br />
| 1<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDCTL|CFG9_CARDCTL]]<br />
| 0x1000000C<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_CARDSTATUS|CFG9_CARDSTATUS]]<br />
| 0x10000010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES0<br />
| 0x10000012<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| CFG9_CARDCYCLES1<br />
| 0x10000014<br />
| 2<br />
| Boot9, Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_SDSLOTCTL|CFG9_SDSLOTCTL]]<br />
| 0x10000020<br />
| 2<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| ?<br />
| 0x10000100<br />
| 2<br />
|<br />
|-<br />
| style="background: red" | No<br />
| [[#CFG9_EXTMEMCNT9|CFG9_EXTMEMCNT9]]<br />
| 0x10000200<br />
| 1<br />
| NewKernel9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_MPCORECFG|CFG9_MPCORECFG]]<br />
| 0x10000FFC<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_BOOTENV|CFG9_BOOTENV]]<br />
| 0x10010000<br />
| 4<br />
|<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_UNITINFO|CFG9_UNITINFO]]<br />
| 0x10010010<br />
| 1<br />
| Process9<br />
|-<br />
| style="background: green" | Yes<br />
| [[#CFG9_TWLUNITINFO|CFG9_TWLUNITINFO]]<br />
| 0x10010014<br />
| 1<br />
| Process9<br />
|}<br />
<br />
== CFG9_SYSPROT9 ==<br />
CFG9_SYSPROT9 is used to permanently disable certain security-sensitive ARM9 memory areas until the next hard reset.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM9 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 1<br />
| Disables [[OTP_Registers|OTP area]] when set to 1. Cannot be cleared to 0 once set to 1.<br />
| NewKernel9Loader, Process9<br />
|-<br />
| 31-2<br />
| Not used<br />
|<br />
|}<br />
<br />
On Old 3DS, NATIVE_FIRM reads CFG9_SYSPROT9 to know whether it has previously initialized the TWL console-unique keys using the OTP data. After setting the TWL console-unique keys, NATIVE_FIRM sets CFG9_SYSPROT9 bit 1 to disable the OTP area. In subsequent FIRM launches prior to the next reset, NATIVE_FIRM will see that the OTP area is disabled, and skip this step.<br />
<br />
On New 3DS, the above is instead done by the [[FIRM#New_3DS_FIRM|Kernel9 loader]]. In addition to using the OTP data for initializing the TWL console-unique keys, the Kernel9 loader will generate the decryption key for NATIVE_FIRM. The final keyslot for NATIVE_FIRM is preserved, so that at a non-reset FIRM launch, the keyslot can be reused, since the OTP would then be inaccessible.<br />
<br />
== CFG9_SYSPROT11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Disables ARM11 [[Memory_layout|bootrom]](+0x8000) when set to 1, and enables access to [[Memory_layout|FCRAM]]. Cannot be cleared to 0 once set to 1.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== CFG9_RST11 ==<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Presumably takes ARM11 out of reset. Cannot be set to 1 once it has been cleared.<br />
| Boot9<br />
|-<br />
| 31-1<br />
| Not used<br />
|<br />
|}<br />
<br />
== 0x10000008 ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| ?<br />
|<br />
|-<br />
| 3-2<br />
| AES related? Value 3 written after write to AES_CTL.<br />
| Boot9, Process9, TwlProcess9<br />
|-<br />
| 31-4<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_CARDCTL ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 1-0<br />
| Gamecard active controller select (0=NTRCARD, 1=?, 2=CTRCARD0, 3=CTRCARD1)<br />
| Process9<br />
|-<br />
| 8<br />
| Enable gamecard eject IRQ, maybe?<br />
| Process9<br />
|}<br />
<br />
Depending on the gamecard controller that has been selected, one of the following gamecard registers will become active:<br />
* Selecting NTRCARD will activate the register space at [[NTRCARD|0x10164000]].<br />
* Selecting CTRCARD0 will activate the register space at [[CTRCARD|0x10004000]].<br />
* Selecting CTRCARD1 will activate the register space at [[CTRCARD|0x10005000]].<br />
<br />
== CFG9_CARDSTATUS ==<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Cartridge-slot empty (0=inserted, 1=empty)<br />
| Process9<br />
|-<br />
| 3-2<br />
| ?<br />
| Process9<br />
|}<br />
<br />
== CFG9_SDSLOTCTL ==<br />
CFG9_SDSLOTCTL controls power and SD card detect?<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0-3<br />
| Powers on the SD card slot when unset. Each bit does the same? If bit 2 is set the 3DS hangs somewhere after SD init.<br />
| Process9<br />
|-<br />
| 8<br />
| ? This bit seems to do nothing.<br />
| Process9<br />
|-<br />
| 9<br />
| Enables SD card detection?<br />
| Process9<br />
|}<br />
<br />
== CFG9_EXTMEMCNT9 ==<br />
This register is New3DS-only.<br />
<br />
{| class="wikitable" border="1"<br />
! Bit<br />
! Description<br />
! Used by<br />
|-<br />
| 0<br />
| Hide extended ARM9 memory (0=hidden, 1=shown)<br />
| Kernel9 (New3DS)<br />
|-<br />
| 31-1<br />
| Reserved<br />
|<br />
|}<br />
<br />
== CFG9_MPCORECFG ==<br />
Identical to [[PDN#PDN_MPCORE_CFG|PDN_MPCORE_CFG]].<br />
<br />
== CFG9_BOOTENV ==<br />
This register is used to determine what the previous running FIRM was. Its value is kept following an MCU reboot. Its initial value (on a cold boot) is 0. NATIVE_FIRM [[Development_Services_PXI|sets it to 1]] on shutdown/FIRM launch. [[Legacy_FIRM_PXI|LGY FIRM]] writes value 3 here when launching a TWL title, and writes value 7 when launching an AGB title.<br />
<br />
NATIVE_FIRM will only launch titles if this is not value 0, and will only save the [[Flash_Filesystem|AGB_FIRM savegame]] to SD if this is value 7.<br />
<br />
== CFG9_UNITINFO ==<br />
This 8-bit register is value zero for retail, non-zero for dev/debug units.<br />
<br />
== CFG9_TWLUNITINFO ==<br />
In the console-unique TWL key-init/etc function the ARM9 copies the u8 value from REG_UNITINFO to this register.<br />
<br />
This is also used by TWL_FIRM Process9.</div>
Profi200