Line 4: |
Line 4: |
| struct DmaConfig { | | struct DmaConfig { |
| sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care. | | sint8_t channel_sel; // @0 Selects which DMA channel to use: 0-7, -1 = don't care. |
− | uint8_t endian_swap_size; // @1 Accepted values: 0=none,2=16bit,4=32bit,8=64bit. | + | uint8_t endian_swap_size; // @1 Accepted values: 0=none, 2=16bit, 4=32bit, 8=64bit. |
− | uint8_t flags; // @2 bit0: DST_CFG, bit1: SRC_CFG, bit2: SHALL_BLOCK, bit3: ???, bit6: DST_ALT_CFG, bit7: SRC_ALT_CFG | + | uint8_t flags; // @2 bit0: DST_CFG, bit1: SRC_CFG, bit2: SHALL_BLOCK, bit3: ???, bit6: DST_ALT_CFG, bit7: SRC_ALT_CFG |
| uint8_t padding; | | uint8_t padding; |
− | uint8_t dst_cfg[10]; | + | DmaSubConfig dst_cfg; |
− | // @5 Accepted values (u8): 4, 8, 12, 15. | + | DmaSubConfig src_cfg; |
− | // @15 Accepted values (u8): 4, 8, 12, 15. | + | } |
− | uint8_t src_cfg[10]; // @14 | + | |
| + | struct DmaSubConfig { |
| + | uint8_t peripheral_id; // @0 |
| + | uint8_t unk2; // @1 Accepted values: 4, 8, 12, 15 |
| + | uint16_t unk3; // @2 |
| + | uint16_t transfer_size?; // @4 |
| + | uint16_t unk4; // @6 |
| + | uint16_t transfer_stride?; // @8 |
| } | | } |
| | | |
Line 16: |
Line 23: |
| | | |
| If CFG or ALT_CFG is not set, default configuration is loaded: | | If CFG or ALT_CFG is not set, default configuration is loaded: |
− | FF 0F 80 00 00 00 80 00 00 00
| |
| | | |
− | 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.
| + | .peripheral_id = 0xFF, |
| + | .unk2 = 0xF, |
| + | .unk3 = 0x80, |
| + | .transfer_size = 0, |
| + | .unk4 = 0x80, |
| + | .unk5 = 0, |
| | | |
− | The format of src_cfg/dst_cfg is unknown, but both have the same format. Checks suggest that the second byte of cfg equalling 4 means NO_INCREMENT (don't increment after read/write).
| + | Checks suggest that unk2 of DmaSubConfig equalling 4 means NO_INCREMENT (don't increment after read/write). |
| | | |
− | Each src/dst config:
| + | 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. |
− | struct DmaSubConfig {
| |
− | uint8_t peripheral_id; // @0
| |
− | uint8_t unk2; // @1 Seen: 2
| |
− | uint16_t unk3; // @2
| |
− | uint16_t transfer_size?; // @4
| |
− | uint16_t unk4; // @6
| |
− | uint16_t unk5; // @8
| |
− | }
| |
| | | |
| 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... | | 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... |