Views: 30,097,946 Homepage | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search 03-12-26 04:24 PM
Guest:

0 users reading GBAtek addendum/errata | 2 bots

Main - Development - GBAtek addendum/errata Hide post layouts | New reply

Pages: 1 2 3
kuratius
Posted on 04-24-25 02:42 PM (rev. 4 of 04-24-25 07:20 PM) Link | #7653
Posted by PoroCYon

Aptina MT9V113 internal MCU stuff


The Aptina cameras have an internal 68HC11-based MCU. Parts of its address space can be accessed through the XDMA registers (0x98c, 0x990, reachable over I2C)
There's a "physical" address range (0x0000..0x1fff) and a "virtual"/"logical" one (0x2000..0x3fff). The former can be used to access "system" and "user RAM" (resp. 0x0000..0x03ff and 0x0400..0x7ff), as well as "Special Function Registers" (SFRs), basically just MMIO regs of the HC11. The latter allows access to the variable spaces of several "firmwares"/"services" running on the MCU, used for autofocus, autowhitebalance, etc. Each camera has a separate HC11.

The above is already kinda known, but now for the new stuff. (Keep this section of GBATEK at hand while reading this, as I guess only a handful people ever looked at the cameras to begin with.)

(NOTE: as the HC11 is an 8/16-bit MCU, pointers etc. are 16-bit (its address space is 16 bits wide). Also, it's a big-endian architecture, keep that in mind.)

SFRs

  • 0x1040: watchdog reset: write 0 to this address to calm down the watchdog timer.
  • 0x1048: "high-precision timer": 32-bit timer value that probaly increases by 1 every 16 MHz tick.
  • 0x1050: "pagetable" pointer: pointer to a list of 16 addresses used to determine to which physical addresses the virtual ones will resolve.
  • 0x1060..0x1066: "ring bus access" or so, not too sure what this is, but it looks like it gives you some sort of DMA access. Sadly, I don't know which registers in this range are address ones, and which ones are used for data.
  • 0x1070: GPIO (already documented on GBATEK, didn't touch it myself.)

Address translation


As alluded to in the previous part, SFR 0x1050 is used to set the mapping. Its value is 0x0100, which means we can access and modify the "pagetable mapping" over I2C. (I'm using quotes here because it's far from anything like a real MMU.)

At 0x0100, a list of 16 pointes can be found: 0x0140 (MONITOR), 0x0000 (SEQ), 0x005d (AF), 0x0165 (AWB), 0x01d4 (FD), 0, 0, 0x282 (MODE), 0, 0, 0, 0x0220 (HG), and then more zeros.

This matches what you'll find when dumping the 0x2000..0x2fff area. While system RAM has space for 16 more pointers (starting at 0x0120) for addresses 0x3000..0x3fff, in practice these are mirrors of the 0x2*** range.

Setting a pagetable entry to an address of 0x2000 or higher seems to return 0 values, maybe there's a carveout, or maybe there's just nothing behind those addresses. Additionally, it does seem to mirror the upper half of memory (0x8000 and up) to the lower half, which is *quite* suspicious as a datasheet says there's 32 kilobytes of firmware ROM, and the exception vectors of the HC11 are at 0xfffe etc. (6502-style) So I'm betting the firmware ROM is in the upper half of MCU memory.

System RAM layout


With the above, we can start building a map of the system RAM space. As one datasheet (links at the end of this post) alludes to the stack of the HC11 firmware also being in system RAM and being 128 bytes in size, it's not too hard to guess where it is.
  • 0x000..0x047: SEQ
  • 0x05d..0x0c0: AF
  • 0x100..0x11f: page table
  • 0x120..0x13f: unused shadow pagetable? idk
  • 0x140..0x168: MONITOR
  • 0x165..0x1d2: AWB
  • 0x1d4..0x1f4: FD
  • 0x220..0x286: HG
  • 0x282..0x2ea: MODE (yes this overlaps with HG)
  • 0x300..0x37f: ??? (maybe stack but I doubt it)
  • 0x380..0x3ff: stack
The 0x380 region seems to be 0xdeadbeef (big-endian)-filled and grows from high addresses to low ones. Additionally, it's one of the RAM regions that seems to get reset regularly (see below). This gives me a relatively high conficence to say it is the stack of the HC11.

User RAM (0x0400 and on) doesn't seem to be writable, sadly. Or maybe I'm missing some kind of magic switch.

Running code on the HC11


A datasheet alludes to using the MONITOR variables to run code: arg1 is the pointer of the code to run, arg2 an optional argument (where is this put in? the accumulators?), and then set cmd to 0x01 to start the code.

Sadly, this did not work for me: it resets the MCU, while doing not much else. Maybe it needs some kind of CRC (which the datasheet also alludes to), or maybe the feature is just locked away. (EDIT: maybe the resetting thing would be added to have the XDMA thing avoid messing with internal state. But does using the virtual addressing mode bypass it? Would chaining using another peripheral (the "ring bus access" maybe?) be able to be used as a bypass? I haven't tested.)

Then I tried putting some shellcode in low system RAM and filling the stack with bad addresses (that is at the same time a NOP sled). Sadly this didn't work either, as the MCU also got reset before it got to execute my code. Maybe I'm triggering some kind of (bad) crash, or maybe there's a safety mechanism that automatically resets everything. (I hope it's not the latter.)

(MCU resets seem to clear/reset the pagetable, stack (0x0380 and up), and some of the "logical variable" spaces in system RAM. 0x300..0x37f seems to be preserved, as well as some other small places in low system RAM.)

Maybe this is a fun challenge for someone else here? :P

P.S. I used Pk11's dsi-camera proof-of-concept as a base to mess with the cameras. Not really publishing my code because it's mostly just a spaghetti of I2C accesses and FIFO ugliness. I used vasm as HC11 assembler, though be aware that it gets some opcodes wrong, check with A09 (which doesn't seem to be able to process "org" directives) and this and this opcode listing I found. For more info on the HC11, see this (original DIP CPU info) and this (more modern microcontroller impl, only gave it a cursory glance, idk how useful it is outside of the instruction set info).

Datasheets

Also a neat link: https://files.niemo.de/aptina_pdfs/



Some additions to this:
The MCU getting reset might be due the homebrew driver you used as a base sending a reset command every frame.
The 1ADC, 2ADC referred to on some row speed settings on gbatek refers to low power mode in the readmode setting. 1ADC is low power mode.
The pixel output clock can be calculated as
16.76 MHz *M/(N+1)/8/2

And correspondingly the frame rate should be pixel clock/(frame_length_lines*line_length_pck).
There's another way to calculate it based on coarse and fine integration time
integration_fps=pixel_clock/(coarse_int_time*line_length_pck+fine_int_time);
Usually this this is more accurate for the actual camera FPS with auto exposure if you read out the current values in the registers.


Here's some logs of the I2Cs Comms in FaceTraining's DSi version in melonDS if you force the arm7 to jump to the function that changes frame rate. Preset12 and above appear to be invalid; it does a bounds check on the contents of R1 if you jump to the function.
The function is at address 037dec10
and expects R0 to contain some sort of camera model id, I recommend just setting all the bits to 1, and R1 to contain the number of the preset.
FrameRatePresetRegisterWrites.zip

Arisotura
Posted on 07-07-25 01:39 PM Link | #7804
speaking of camera


I never posted about the camera interface thing, and GBAtek doesn't say a lot, so


CAM_CNT:

* if a camera transfer is underway, clearing bit15 is delayed until the end of that transfer


CAM_DAT:

* data FIFO holds 512 words
* there are two FIFOs

when a FIFO is full (ie. contains as many scanlines as the DMA interval set in CAM_CNT)
* if the other FIFO is empty (was fully read): swap FIFOs, fire DMA
* if not: raise overrun error

transferring too many scanlines per block doesn't raise the overrun error
reading too much of the FIFO doesn't raise the overrun error

____________________
Kuribo64

Arisotura
Posted on 08-07-25 07:54 PM (rev. 3 of 08-09-25 12:30 AM) Link | #7855
audio related


POWCNT2:

* "Note: Bit0 disables the internal Speaker only, headphones are not disabled." - not true. bit0 does disable headphone output too.
* on the DSi, bit0 only disables NITRO mixer output, not DSP output.
* also, only disables output -- mixer still runs
* does disable SOUNDBIAS too


MIC_CNT:

* mic mode/freq bits can't be changed while bit15 is set
* IRQ bits, however, can be changed

IRQ bits:
* 0 = none
* 1 = when FIFO half-full
* 2 = when FIFO full (seems to actually be overrun IRQ)
* 3 = both

IRQ triggers just once (ie. not like GXFIFO IRQ)

____________________
Kuribo64

Arisotura
Posted on 09-14-25 12:39 PM (rev. 3 of 09-14-25 02:06 PM) Link | #7948
CAM_MCNT:

is read-only when the camera transfer is enabled.

doesn't actually reset anything - none of the bits have any effect on the other camera registers.

except bit 5, which goes to the cameras' reset lines.

bit 7 seems to be set all the time.

theory: might be a GPIO thing?

EDIT- https://melonds.kuribo64.net/board/thread.php?pid=6140#6140

still weird.

____________________
Kuribo64

Jakly
Posted on 12-07-25 09:30 AM (rev. 2 of 12-07-25 09:40 AM) Link | #8164
Notes and Findings on NDS ARM946E-S Pipelining and Timings:

All research has been performed on a new3DSxl in TWL mode; some details may vary based on HW revision or other misc factors. The subject is also very complex and thus hard to comprehensively verify all factors, so some parts of it may be speculative.


ARM9E-S processors use a 5 stage pipeline:
Fetch: future instruction data is read off of the bus
Decode: the next instruction is decoded.
Execute: most instruction logic is handled here.
Memory: Some extra instruction logic is optionally handled here. All instructions spend at least 1 cycle in the memory stage, even if no logic is performed during it.
Writeback: instruction results are written back to the register bank. Some load instructions finalize output in this stage.


Forwarding and Interlocks:
To alleviate the effects of the longer pipeline the cpu will attempt to use shortcut paths to send results to instructions that need them ahead of them being properly written back.
In some cases the results may not be available immediately, this results in later instructions in the pipeline being delayed. This is called interlocking.
Note that interlocks to R15 will always be incurred as you immediately need the result for the branch address. Side note: MRC is implemented as a load from coprocessor, and amusingly, MRC R15 being a load to the CPSR flag nibble results in timing behavior consistent with the interlock being triggered by the decode stage.

It’s worth noting there are two types of interlock: Types A/B & Type C.
This is due to the internal ports used to fetch a given operand from. Certain register writeback paths don’t have paths to the C register bank port. Type C interlocks are confirmed to happen for LDR/LDM results and take an extra cycle to resolve for store (Rd, not base) & multiply accumulate inputs. (Speculation: is this because both of those are registers being read during the memory stage…?)


Speculation on how pipeline stages overlaps:
It’s unclear when exactly the Decode stage occurs, it might be possible to infer it somehow, though it’s not particularly important so I haven’t tried yet.
Execute stage seems to begin on the last cycle of the Fetch or previous Memory stage, whichever takes longer, this results in a 1 cycle overlap.
The Fetch stage begins the cycle after the Execute stage ends.
The Memory stage seems to usually begin the cycle after the Execute stage ends; note that this doesn’t quite apply to LDM/STM.
The Writeback stage begins the cycle after the memory stage ends.

LDM/STM seem to be unique in that they can overlap the Execute stage and Memory stage. With the memory stage beginning on the second cycle of the instruction and the execute stage lasting for one cycle per memory access; this should also apply to LDRD/STRD as they are internally LDM/STM. The writeback stage allegedly also occurs once per access after each individual one completes, though this doesn’t seem too useful to model. Note: I’m not 100% sure how SWP works here?


Multi-bus drifting?!:

ARM946E-S has 3 internal buses:
Instruction Bus.
Data Bus.
Write Buffer Bus.


ITCM: Sane as long as you never try to access it on the data bus. Data read (writes are weird?) accesses to ITCM seem to stall the instruction bus for 1 cycle. This has been observed with instruction accesses to ITCM, ICache, and the latched halfword thumb instruction fetches use. This has not been confirmed to occur on instruction fetches from uncached external bus accesses or actively streamed in external bus accesses. It has not yet been tested with prefetch aborts.

Writes on the data bus stall the data bus for one cycle if you attempt to read from it on the next cycle. This has been confirmed for writing both DTCM and the Write Buffer.


AHB buffer latency:
All accesses to the external bus (AHB) must go through an internal buffer for some reason that i dont fully understand that adds a disgusting amount of latency.
The buffer takes 3 bus cycles when using a 2:1 cpu:bus clock ratio and 2 bus cycles with 4:1.
Buffering is only done while the ARM9 has confirmed ownership of the AHB.
The ARM9
If the ARM9 loses ownership of the bus for any reason then all accesses must be rebuffered from scratch.
When the ARM9 has ownership all 3 internal buses can queue up accesses, and ownership is not relinquished until all 3 queues are empty, this can result in the latency being hidden partially or fully under some circumstances.
The ARM9 (probably?) can’t lose ownership of the external bus while buffering. (I guess this is the same or similar logic that prevents being interrupted in the middle of an individual fetch?)
Note that the ARM9 seemingly will never queue up an access to the AHB if it is sequential and an access is still finishing on the current bus. I don’t know why, it just is.
Note that an internal bus cannot be interrupted by another internal bus or itself until its current burst is finished.
I wanna say priority in case of a tie is data > instruction > wb but that’s not something i’ve confirmed.


Bus alignment:
The ARM9 runs at a higher clock relative to the AHB, this means that any accesses to it will stall until aligned with the bus clock.
Note that bus is rising edge which apparently results in results being attained on the first cycle of a given bus cycle. So a 2 cycle access to the AHB would finish in 3 ARM9 cycles rather than 4. This point tends to be largely moot due to alignment requirements but it can be used to interweave extra instructions between two different accesses.


Cache streaming jank:
Cache streaming allows the processor to continue executing to a limited extent while cache line fills occur in the background
While a cache stream is active, attempting a nonsequential access on that bus will result in it stalling until the stream is fully complete, this includes internal accesses and latency will be incurred if to the AHB.
If the next streamed in word finishes streaming in before the arm9 wants it, this will count as a nonsequential access and you will be forced to wait until the stream is fully complete to get the data.

Arisotura
Posted on 01-04-26 01:38 PM (rev. 24 of 01-25-26 12:32 PM) Link | #8267
not sure if I posted before about 2D stuff

anyway

* internal rotscale reference points are updated even when forced blank is enabled in DISPCNT.
* same goes for mosaic counters.

also, mosaic weirdness, when changing it midframe:

* BG mosaic: Y counter keeps counting until the old Y size is reached, then uses new Y size
* OBJ mosaic: Y counter keeps counting until the new Y size is reached. if the new Y size is smaller than the old one, it will wrap around (the counter is 4 bits).
* in both cases, the new X size applies immediately.

* OBJ mosaic counter is NOT updated when the OBJ layer is disabled.
* TODO: check if it's the case for BG layers (and if they have separate counters, too)
* also, internal BG reference points are not updated when the corresponding layer is disabled.


* THEORY: internal rotscale reference points are updated during VBlank too.
* possibly also the case for mosaic counters.


WHEN DISABLING BG/OBJ LAYERS OR ENABLING FORCED BLANK

* disabling BG/OBJ layers or enabling forced blank midframe applies immediately.
* enabling layers or disabling forced blank takes two scanlines to apply.
* however, the OBJ mosaic counter starts counting again immediately when the OBJ layer is re-enabled. (TODO: verify for BG layers)
* disabling/enabling windows applies immediately.


WHEN DISABLING A 2D UNIT VIA POWCNT1

* internal rotscale ref points, and mosaic counters, aren't updated
* TODO check if windows are updated
* unit B outputs white.
* unit A outputs black.
* when re-enabling, the next OBJ scanline will be what it was prior to disabling (due to rendering sprites one scanline in advance)

* POWCNT1 bit1 does not affect VRAM display (and presumably mainRAM FIFO)
* does not affect master brightness (still applied to the "disabled" output)
* does not affect display capture

* disabling a 2D unit between scanlines 262 and 0 causes it to not properly reset the rotscale ref points
* same goes for the mosaic counters

POWCNT1 BIT 0

seems to cut off the LCD video signal? as well as the power, presumably.

toggling that bit midframe does weird shit. prolly not good for hardware. two of my DS's emit repeated clicks when doing this.

when disabling the screens, they become black, backlight off.
when enabling them, they seem to stay black or white (? prolly depends on screen make/etc) for a moment before displaying.


VCOUNT

register is 9 bits wide.

it gets reset to 0 at the end of scanline 262, normally.

but you can write whatever value to it. (it gets applied at the next scanline)

if you set it to 263, the next VCount is 264, and so on. it just keeps counting until it reaches 511 and wraps back to 0.

if you set it to 262 or more, and the previous VCount is 192..260, the VBlank flag in DISPSTAT doesn't get cleared until the end of the next frame. this also suppresses the VBlank IRQ for the next frame.

if you set it to 262 or more while the previous VCount is 261, the VBlank flag does get cleared.

order of operations:
1. at end of scanline, VCount is incremented
2. VCount is checked for values 192 or 262, to adjust the VBlank flag (and raise IRQ upon rising edge)
3. if a value was written to VCount, it is applied
4. VMatch


WRITING VCOUNT DURING ACTIVE DISPLAY

if VCount is advanced, ie. scanlines beyond 191 end up on screen: I thought it would just display white pixels, but it's weirder than that, and what actually happens seems to depend on hardware. different results observed on DSPhat, DSLite, DSiXL.

might be entirely up to the LCD itself, since apparently this messes with the video signal... I wanted to test with my capture-card DS, but the capture card just gives up in that situation. I guess it doesn't receive enough data to form a full frame, or something.


DISPLAY CAPTURE

clearing up a few things:
* busy bit in DISPCAPCNT is always cleared upon VBlank, even if the capture size is smaller
* stride for input B (VRAM, and display FIFO, too) is always 256, even if the capture size is 128x128 (which means the output stride is 128)

* DISPCAPCNT is completely writable at any time.
* the capture start bit is latched upon scanline 0 (VCOUNT transition 262->0), and cleared upon VBlank (if and only if it was latched).

* the VRAM address capture writes to is based on VCOUNT.

____________________
Kuribo64

Arisotura
Posted on 01-10-26 11:55 PM (rev. 2 of 01-11-26 02:35 AM) Link | #8278
oh by the way

DISP_MMEM_FIFO

I researched how 8-bit writes work

* byte 0: behaves like a 16-bit write to halfword 0. value is duplicated across the entire halfword.
* byte 1: ignored.
* byte 2: behaves like a 16-bit write to halfword 1. value is duplicated across the entire halfword. does not advance the write pointer.
* byte 3: advances the write pointer. value is ignored.


similarly, for VCOUNT

byte writes just write to one or another half of the VCOUNT override value, and set the 'apply override at next scanline' flag.

____________________
Kuribo64

Arisotura
Posted on 02-20-26 02:13 AM (rev. 7 of 03-07-26 04:56 PM) Link | #8399
CART INTERFACE


* there are separate register sets (and separate cart interfaces) for ARM9 and ARM7
* cart command regs (040001A8) aren't readable

* if the cart interface isn't selected on the current CPU, it only reads FFFFFFFF - the actual hardware still works, just can't access the cart
* doesn't apply if there's no cart inserted - both sides read 00000000
* SPI behaves similarly

* cart commands while no cart is inserted read FFFFFF00 on DS, 00000000 on DSi
* cart commands with ROMCTRL.bit29=0 read garbage (ie FFFF3F00 on DSi)
* SPI works regardless of ROMCTRL.bit29


DSi SPECIFIC

unlike what GBAtek implies, the two interfaces are fully working - there's actually a new EXMEMCNT bit for interface 2 (bit 10)

* interface 1: regs: 040001Ax/04100010, transfer IRQ: 19, cart IRQ: 20, NDMA start mode: 04, EXMEMCNT bit: 11
* interface 2: regs: 040021Ax/04102010, transfer IRQ: 26, cart IRQ: 27, NDMA start mode: 05, EXMEMCNT bit: 10

SCFG_MC

state=0: cart is off
state=1: cart is on but in reset - reads FFFFFFFF
state=2: cart is on and ready
state=3: turn cart off (switch to state 0) after timer

trying to switch to state 1 or 2 with no cart inserted forcefully switches to state 3, and triggers a card IRQ. (same on slot 2, but there's no card IRQ)

ejecting the cart switches to state 3.

switching to state 0 in any way (directly or through state 3) triggers a card IRQ if the cart was previously on.

similarly, switching to state 0 (from a previous on state) clears bit 29 in ROMCTRL.

if a cart is inserted and powered on: toggling bit 15 (interface swap bit) triggers a card IRQ on the interface which was connected to the actual cart (ie to slot 1).

NOTE on bit15: this bit switches which addresses each interface responds to, as well as the IRQ lines, DMA trigger, etc. so, whatever values were in interface 1's registers appear at interface 2's, and vice versa.

LOGIC STUFF

state=0: power off, /RES low, no clock output - reads 00000000 or so
state=1: power on, /RES low, no clock output - reads FFFFFFFF
state=2: power on, /RES high, clock output - reads normal
state=3: power on, /RES low, no clock output - reads 00000000 or garbage

/RES is held low (active) if either the SCFG_MC state is not 2, or if ROMCTRL bit29 is cleared.

however, ROMCTRL bit29=0 doesn't stop clock output.

____________________
Kuribo64

Arisotura
Posted on 02-28-26 12:07 AM (rev. 9 of 02-28-26 07:53 PM) Link | #8415
ROM TRANSFER UPDATE


ROM transfers

* transfer time is 8 cycles for a command, 4 cycles per response word (basically 1 cycle per byte) (see ROMCTRL bit27 for cycle duration)
* plus start delay and 0x200-block delay at the start of each 0x200 block
* bit28 allows skipping incoming bytes automatically during delays
* DELAYS DO NOT APPLY WHEN THE WR BIT IS SET
* DRQ bit (bit23) is set once a response word has been transferred
* reading from 0x04100010 clears the DRQ bit, and:
** if the transfer is finished: clears the busy bit and triggers IRQ if specified
** if there are more words to transfer: begins transferring the next word



transfers when WR=1:

"DELAYS DO NOT APPLY WHEN THE WR BIT IS SET" -> not true.

DRQ gets set immediately after starting a command, for the first data word. for the second data word, it gets set after the command + delays (+ first word?) are transferred.

transfers with no data still cause DRQ to get set, which may cause DMA to fire spuriously (suggesting that the DMA trigger is a level trigger). DRQ will remain set until 0x04100010 is written to.

toggling WR doesn't clear DRQ. writing to 0x04100010 doesn't clear DRQ if WR was cleared.

toggling AUXSPICNT bit13 or bit15 doesn't clear DRQ (and doesn't affect ROMCTRL at all).



GCDATAIN (0x04100010)

this register is a 8-byte FIFO. the same FIFO is used for both transfer directions. reading and writing to GCDATAIN uses the same FIFO pointer (named "FIFO CPU-side pointer" in the lack of a better name - other pointer is on the cart side).

reading from GCDATAIN returns the last FIFO entry. if the WR bit in ROMCTRL is cleared, it also advances the FIFO CPU-side pointer to the next word.

when reading GCDATAIN in 16-bit or 8-bit units: any read will advance the CPU-side pointer.

writing to GCDATAIN only works if the WR bit in ROMCTRL is set. then, it also advances the FIFO CPU-side pointer to the next word.

when writing to GCDATAIN in 16-bit or 8-bit units: 16-bit or 8-bit writes work correctly, but the CPU-side pointer is only advanced when accessing the high-order byte (0x04100013).



HARDWARE BUG when WR=1

if the last delay gap to apply at the beginning of a transfer isn't a multiple of 4, the hardware may accidentally send out one data word even if the FIFO is empty (ie if you fail to respond to the very first DRQ in time). the data that gets sent is whatever was in the FIFO. this glitch will also break the rest of the transfer by causing some weird offsetting (words getting written to GCDATAIN at the same time as they're being sent out).

unsure if this also happens between 0x200-byte blocks.

no idea why or how this even happens.

for example:

gap1=0, gap2=0: no glitch
gap1=1, gap2=0: glitch
gap1=2, gap2=0: glitch
gap1=3, gap2=0: glitch
gap1=4, gap2=0: no glitch

gap1=1, gap2=0: glitch (last gap to apply was gap1)
gap1=1, gap2=1: glitch
gap1=1, gap2=2: glitch
gap1=1, gap2=3: glitch
gap1=1, gap2=4: no glitch (last gap to apply was gap2)

gap1=3, gap2=0: glitch
gap1=4, gap2=0: no glitch


AUXSPICNT bit13/15:

if they're "set wrong", ROMCTRL is still read/writable, but won't start transfers

changing AUXSPICNT won't start a transfer if ROMCTRL bit31 is set. it needs to be toggled again.

clearing AUXSPICNT bit13 during a SPI transfer causes /CS to go high (released). setting that bit again causes it to go back to low (active).

toggling AUXSPICNT bit15 during a SPI transfer has no effect on /CS.

____________________
Kuribo64
Pages: 1 2 3

Main - Development - GBAtek addendum/errata Hide post layouts | New reply

Page rendered in 0.139 seconds. (2048KB of memory used)
MySQL - queries: 29, rows: 98/98, time: 0.028 seconds.
[powered by Acmlm] Acmlmboard 2.064 (2018-07-20)
© 2005-2008 Acmlm, Xkeeper, blackhole89 et al.