Thanks, maybe better the threads are separate.
RP2350A: With the following code (default compiler settings; SDK 2.2.0) the time from active /SRD signal to data out (DBG_OUT_SIG) is 21-22cycles, which is basically the same as with PIO + DMA (a channel getting the addr from PIO RX FIFO and writing it to readAddr of another channel, writing to PIO TX FIFO with the response that for that reg).
(Input synchronizers enabled.)
Assembly (the main part):
Previously-tested PIO code (completely standard: Y preloaded with upper regsRespValues addr bits, two bits under the reg addr bits are always 0 (each reg uses a whole word)):I am not sure when/if I'll test more.
RP2350A: With the following code (default compiler settings; SDK 2.2.0) the time from active /SRD signal to data out (DBG_OUT_SIG) is 21-22cycles, which is basically the same as with PIO + DMA (a channel getting the addr from PIO RX FIFO and writing it to readAddr of another channel, writing to PIO TX FIFO with the response that for that reg).
(Input synchronizers enabled.)
Code:
static inline u32 gpioGetOut(void) {#if PICO_USE_GPIO_COPROCESSOR return gpioc_lo_out_get();#else return sio_hw->gpio_out;#endif}#define nCS 11#define nCS_INV 0#define nSRD 10#define nSRD_INV 0#define ADDR_BASE 12#define ADDR_WDTH 8#define DATA_BASE 0#define DATA_WDTH 8#define DATA_OE_MSK 0xFF#define DBG_OUT_SIG 21void __time_critical_func(core1RegRespArm)(void) {u32 gpioAddrMask = (1<<ADDR_WDTH)-1;const u32 gpioAccsMsk = ((1^nCS_INV)<<nCS) | ((1^nSRD_INV)<<nSRD);const u32 gpioAccsVal = ((0^nCS_INV)<<nCS) | ((0^nSRD_INV)<<nSRD);u32 val, dir, addr, gpioAddr;const u32 gpioDataMask = DATA_OE_MSK;u32 prevData = gpioGetOut() & gpioDataMask;while (1) {addr = ((u32)®RespArr) & ~gpioAddrMask;while (1) {gpioAddr = gpio_get_all();if ((gpioAddr & gpioAccsMsk) == gpioAccsVal) break;//same code as above mostly; more readable}gpioAddr >>= ADDR_BASE;gpioAddr &= gpioAddrMask;addr |= gpioAddr;val = ((vu8*)addr)[0];val <<= DATA_BASE;val ^= prevData;//in shifted stategpio_xor_mask(val);gpio_set_dir_out_masked(gpioDataMask);//enable outgpio_clr_mask(1<<DBG_OUT_SIG);//debug: outEn indicatorprevData = gpioGetOut() & gpioDataMask;while (1) {gpioAddr = gpio_get_all();if ((gpioAddr & gpioAccsMsk) != gpioAccsVal) break;}gpio_set_dir_in_masked(gpioDataMask);gpio_set_mask(1<<DBG_OUT_SIG);//debug: outOff indicator}}Code:
MOVS R0, #0xFFMOV.W R1, #0x200000LDR R4, =regRespArrUXTB R2, R2loc_200001C4prevData = R2 ; u32MRC p0, 0, R3,c0,c8, 0gpioAddr = R3 ; u32TST.W gpioAddr, #0xC00BNE loc_200001C4UBFX.W R3, R3, #9, #0xBORRS R3, R4LDRH R3, [R3]UXTH R3, R3EORS prevData, R3val = R2 ; u32MCR p0, 1, val,c0,c0, 0MCR p0, 2, R0,c0,c4, 0MCR p0, 3, R1,c0,c0, 0MRC p0, 0, val,c0,c0, 0UXTB R2, R2loc_200001ECprevData = R2 ; u32MRC p0, 0, R3,c0,c8, 0gpioAddr = R3 ; u32TST.W gpioAddr, #0xC00BEQ loc_200001ECMCR p0, 3, R0,c0,c4, 0MCR p0, 2, R1,c0,c0, 0B loc_200001C4Previously-tested PIO code (completely standard: Y preloaded with upper regsRespValues addr bits, two bits under the reg addr bits are always 0 (each reg uses a whole word)):
Code:
.program pioRegResp_A.side_set 1 opt//SideSet shows when data is being output (while low). Autopush 32bit, autopull, 32bit, in shift left..wrap_targetpublic entryPoint:in y, (32-10) side 1//Last instr should leave ISR empty.waitAccsNoRst:wait 0 gpio nSRDjmp pin waitAccsNoRst//Check for /CS to this device.in pins, 10out pins, 32//Output data (uses autopull).mov pindirs, !nullwait 1 gpio nSRD//Wait /SRD end.mov pindirs, null.wrap//jmp waitAccsStatistics: Posted by wisi — Fri Dec 26, 2025 4:36 pm