How to run two cogs in Prop-2 assembly language?
JonTitus
Posts: 193
in Propeller 2
I want to run a cog that transmits data and another cog that will independently receive the data and display it on LEDs. Think of two separate UARTs. I have no idea how to set up two independent cogs in assembly language for the Propeller 2 and would appreciate some sort of simple example that shows how to do it. Thank you. --Jon

Comments
CON clkout = 20 ' Pin P20 txout = 21 ' Pin P21 rxin = 31 rxclkin = 30 dat org coginit #%100100, @sync_receive ' init cog-4 for synchronous receive coginit #%100010, @sync_transmit ' init cog-2 for synchronous transmit '==================================== sync_transmit dirl #txout wrpin sync_tx_mode, #txout 'Set up sync tx mode for pin 21 wxpin #%1_00111, #txout 'Set up stop/start mode, X[5] = 1, 8 bits dirh #txout 'Enable Smart Pin dirl #clkout wrpin clock_mode, #clkout 'Set pin P20 as transition-output mode wxpin ##$1000, #clkout 'Set base period for transition output dirh #clkout 'Enable P20 as clock-output .loop waitx ##10_000_000 'Delay between transmissions wypin #$85, #txout '8-bit data to transmit: 10000101 wypin #16, #clkout 'Start clock, transmit data jmp #.loop '==================================== sync_receive mov dira, ##$FF ' Pins P7--P0 for output mov outa, my_test_data 'just a test .dummy nop jmp #.dummy sync_tx_mode long %0000_0111_000_0000000000000_01_11100_0 clock_mode long %0000_0000_000_000000_1_000000_01_00101_0 sync_rx_mode long %0111_0000_000_0000000000000_00_11101_0 my_test_data long $55* You don't need the second COGINIT because cog 1 will keep executing after the COGINITs. In fact, it's likely cog 1 that's running your transmit code, not cog 2 (for the same reason that receive isn't working).
* For each block of code you are going to run in cogexec mode with COGINIT, you should have an ORG 0 at the beginning of the block.
'+-------[ Start SD Driver COG code ]------------------------------------------+ mov id, #16 ' start next cog avail and return cogid setq ##sd_mailbox ' put in PTRA of started cog coginit id, ##@sddriver wc ' starts a free cog, returns cogid (id=16 initially) '+-----------------------------------------------------------------------------+and here is how you load LUT in the current cog'+-------[ Load LUT code ??? ]-------------------------------------------------+ setq2 ##_USER_LUT_END-_USER_LUT_BEGIN-1 '\ load LUT rdlong 0, ##_USER_LUT_BEGIN '/Ok. I had a bit more time to look over the code this morning. A few suggestions:
CON clkout = 40 ' Pin P40 txout = 41 ' Pin 41 rxin = 31 rxclkin = 30 dat org 0 coginit #%0_0_0100, ##@sync_receive ' init cog-2 for synchronous receive '==================================== ' Sync-serial transmit dirl #txout wrpin sync_tx_mode, #txout 'Set up sync tx mode for pin 21 wxpin #%1_00111, #txout 'Set up stop/start mode, X[5] = 1, 8 bits dirh #txout 'Enable Smart Pin dirl #clkout wrpin clock_mode, #clkout 'Set pin P20 as transition-output mode wxpin ##$1000, #clkout 'Set base period for transition output dirh #clkout 'Enable P20 as clock-output .loop waitx ##10_000_000 'Delay between transmissions wypin #$85, #txout '8-bit data to transmit: 10000101 wypin #16, #clkout 'Start clock, transmit data jmp #.loop '==================================== sync_receive org 0 mov dira, ##$00FF ' Pins P7--P0 for output mov outa, my_test_data 'just a test .dummy nop jmp #.dummy sync_tx_mode long %0000_0111_000_0000000000000_01_11100_0 clock_mode long %0000_0000_000_000000_1_000000_01_00101_0 sync_rx_mode long %0111_0000_000_0000000000000_00_11101_0 my_test_data long $55It should start cog 1 (first free cog) and return the cogid of the started cog into id. If it works then output id to the pins instead of $55 to see that it did indeed start cog 1.
CON clkout = 40 ' Pin P40 txout = 41 ' Pin 41 rxin = 31 rxclkin = 30 dat org 0 ' coginit #%0_0_0100, ##@sync_receive ' init cog-2 for synchronous receive coginit id, ##@sync_receive wc ' init cog-2 for synchronous receive '==================================== ' Sync-serial transmit dirl #txout wrpin sync_tx_mode, #txout 'Set up sync tx mode for pin 21 wxpin #%1_00111, #txout 'Set up stop/start mode, X[5] = 1, 8 bits dirh #txout 'Enable Smart Pin dirl #clkout wrpin clock_mode, #clkout 'Set pin P20 as transition-output mode wxpin ##$1000, #clkout 'Set base period for transition output dirh #clkout 'Enable P20 as clock-output .loop waitx ##10_000_000 'Delay between transmissions wypin #$85, #txout '8-bit data to transmit: 10000101 wypin #16, #clkout 'Start clock, transmit data jmp #.loop '==================================== sync_receive org 0 mov dira, ##$00FF ' Pins P7--P0 for output mov outa, my_test_data 'just a test .dummy nop jmp #.dummy sync_tx_mode long %0000_0111_000_0000000000000_01_11100_0 clock_mode long %0000_0000_000_000000_1_000000_01_00101_0 sync_rx_mode long %0111_0000_000_0000000000000_00_11101_0 my_test_data long $55 id long 16sync_receive needs to be moved after the cog 0. It would otherwise be getting the address in cog just after the jmp #.loop instruction. ie its int the wrong cog space.
That shouldn't matter here because it's the hub address of sync_receive that he needs, right?
Ok, so when you added the second "ORG 0", you reset the cog address counter, including for "sync_tx_mode" and "clock_mode". Simply move them above "sync_receive" (technically, above the second "ORG 0"), so that their addressing is relative to the first block of cog code.
Also, I recommend following @Cluso99's advice about dynamically allocating the receive cog. As you re-use code snippets, this keeps you from having to manually adjust cog allocation.
Later this afternoon I discovered something similar with loading LUT. A few gotchas around placing the labels in the right position for it to work properly.
' Synchronous serial transmission, Rev. 3, 06-13-2020 at 1007 MDT 'positive edge-trigger (Jon Titus) CON clkout = 40 ' Pin P40 txout = 41 ' Pin 41 rxin = 31 rxclkin = 30 dat org 0 coginit id, ##@sync_receive ' init cog-2 for synchronous receive '==================================== ' Sync-serial transmit dirl #txout wrpin sync_tx_mode, #txout 'Set up sync tx mode for pin 21 wxpin #%1_00111, #txout 'Set up stop/start mode, X[5] = 1, 8 bits dirh #txout 'Enable Smart Pin dirl #clkout wrpin clock_mode, #clkout 'Set pin P20 as transition-output mode wxpin ##$1000, #clkout 'Set base period for transition output dirh #clkout 'Enable P20 as clock-output .loop waitx ##10_000_000 'Delay between transmissions wypin #$85, #txout '8-bit data to transmit: 10000101 wypin #16, #clkout 'Start clock, transmit data jmp #.loop sync_tx_mode long %0000_0111_000_0000000000000_01_11100_0 clock_mode long %0000_0000_000_000000_1_000000_01_00101_0 id long 16 '==================================== org 0 sync_receive mov dira, ##$00FF ' Pins P7--P0 for output mov outa, my_test_data 'just a test .dummy nop jmp #.dummy sync_rx_mode long %0111_0000_000_0000000000000_00_11101_0 my_test_data long $81I'm glad you were able to get it working! Is this your first multi-cog program? I still remember my feeling of elation the first time I went multi-cog. Admittedly, that was on the P1, but that feeling has never really diminished.