Shop OBEX P1 Docs P2 Docs Learn Events
Active Low Chip Select With Assembly Routine — Parallax Forums

Active Low Chip Select With Assembly Routine

sobakavasobakava Posts: 33
edited 2014-01-10 20:51 in Propeller 1
I'm trying to make an assembly based serial (SPI master) routine. My device has standart chip-select, clock and data signals. But chip-select is Active Low.

I'm confused with how to handle output direction and status of CS signal between main program (SPIN) and my assembly routine.

parallax_cog_shiftout.jpg


I tried to draw what I'm trying to do. In my main program, I put 32bit data into a variable and start a new cog for my assembly routine. In the ASM, I generate a clock signal. Shift out and shift in data using IO pins. It is really fast and I liked it. When I probe the signals with oscilloscope, everything seems fine except the CS signal. It creates only a very short duration HIGH pulse.

Should I define CS signal in main program (SPIN) as output as well? What should be the DIRA and OUTA status in main program? Briefly, how can I make CS low only in the ASM routine and let it remain HIGH outside ASM routine? I also tried to control CS pin at the SPIN side before and after COG operation but it became much much slower than my shift IN/OUT operations.

I know outputs are ORed in the P.Propeller. So, it would be really easy to do this if the CS would be an active HIGH signal.

I found some SPI assembly objects on OBEX but I want to write my own rouine and frankly, I want to understand why this is not working.

Thank you
1024 x 654 - 40K

Comments

  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-01-09 12:19
    I would favor controlling the chip select from PASM. Your Spin program would pass a message to do something and all the signallig would be handled on the PASM side. Remember that DIRA register bits must be set in the cog accessing the pin.

    BTW, are you aware of the ANDN instruction? It works like AND but uses the inverted value of your mask. Assuming pin has been made an output, you can set it high (disable) with OR, and take it low (enable) with ANDN -- using the same mask.

    Edit: Looking more closely at your diagram, if you're stopping the cog that controls the CS pin, you should pull that pin high through a resistor so that the device is deselected after you stop the cog.
  • tonyp12tonyp12 Posts: 1,951
    edited 2014-01-09 12:24
    You got the whole concept of using cognew/cogstop as a object you call often (not right)
    If you want to create a SPI Master that is written in pasm (in a new cog of course)

    1: Spin sets up a buffer variable (data) plus a flag variable that you should put before the buffer space,
    so the pasm cogs know when new data is there and clear it when done.

    2: Start the pasm cog with cognew pointing to the flag variable, the cog will use PAR for this address.
    3: cog sets up DIRA and OUTA, as each cog must sets it's own.
    3: run a loop rdlong t1,PAR wz ; get 1 as ready or use length-of-data if variable lengths happens
    if_z jmp #3
    4 : andn CSpin
    5: mov t2,PAR
    6: add t2,#4
    7: rdlong t3,t2
    8: rol t3(data),muxc pin, or & andn clock pin.
    innerloop
    9: or CSpin
    10: jmp to 3
  • MagIO2MagIO2 Posts: 2,243
    edited 2014-01-09 16:10
    As Tony already said the most used concept of operation is different. Driver COGs like this usually sit in background and wait for commands instead of being started. Reason:
    1. drivers usually drive I/O pins and this is much easier with the COG staying alive as you already found out. Otherwise you need synchronization with another COG that takes over the I/Os - or use external resistors which keep them in a defined state - like Jonny said.
    2. starting a COG always needs some time which reduces the response time to your task that wants to send something via SPI.

    The nice thing with this kind of background waiting COG is that you can create a basic skeleton (like sketched by Tony) and use it over and over again for different drivers. So it's a good investment to try to understand what Tony said and go this route instead.
  • sobakavasobakava Posts: 33
    edited 2014-01-10 11:39
    Thank you all guys. I think I understood the COG/ASM concept this time. I'm working on modifying the code now. I won't stop the COG and it will watch a flag to initiate a read/write all the time. I would like to make it as an object and share it with people in OBEX.

    By the way, can I use two unused physical IO ports between main COG and SPI cog instead a flag located in HUB memory?
  • JonnyMacJonnyMac Posts: 9,107
    edited 2014-01-10 20:51
    By the way, can I use two unused physical IO ports between main COG and SPI cog instead a flag located in HUB memory?

    You can for your own project, but if you're going to make this universal and share it, you cannot count on others having available IO pins for use as flags.
Sign In or Register to comment.