You are here

Problem with interrupts and output pins... | Cypress Semiconductor

Problem with interrupts and output pins...

Summary: 14 Replies, Latest post by odissey1 on 05 Dec 2016 10:42 AM PST
Verified Answers: 2
Last post
Log in to post new comments.
paul.chambre_1977636's picture
User
44 posts

I'm still stuck on a couple of things with my project. This is a project to add SD storage and BLE communications to a 1982 pocket computer. I'm trying to interface the PSoC to LH5801 CPU by emulating RAM. I am able to write data from the MCU to the CPU, but things are breaking down when I try to read the data bus and use the R/W signal.

Right now, I have a decoded CS on P0.5. This has an interrupt on falling edge that triggers the main routine to read the address bus and see what needs to be done. The R/W line goes to P0.4, and is also ANDed with the inverted CS signal to control OE of the data bus pins.

Looking at the timing diagrams for the PC, it seems that R/W pulses low after address and data are set up when writing to memory. So, I would like to have an interrupt on R/W that gets enabled when CS goes low, and disabled when CS goes high. The W interrupt handler would then read the data bus and write the data to MCU memory.

The problem I'm stuck on is that I can't find how to enable interrupts for both P0.4 and P0.5, and, when I tried to move R/W to one of the remaining available pins (P4.0-1, or P5.0-1) the designer tells me that the function is not reachable from those pins. I can't use anything on P1, P2, or P3, because those ports are fully allocated for address and data lines.

I thought there was a way to have more than one interrupt per port. Can someone tell me more about this, or how I can use P4 or P5?

Thanks,
​Paul

user_1377889's picture
User
9606 posts

For (most) PSoC4 chips all ports >= 4 cannot be routed to a signal but can be read or written to by firmware.

The only remaining pins are P0_6 and P0_7 which are currently used for debugging.

Consider connecting the interrupts to the signals coming from the input pins (or the output of the not-gate).

 

Bob

paul.chambre_1977636's picture
User
44 posts

Hmmm... one thing I wanted to try, since it's supposed to be faster, was using CY_GET_REG8 and CY_SET_REG8 instead of Read and Write... however, these don't seem to work. If I replace:

Pin_Data_Write(buffer[laddress]);

with

CY_SET_REG8(CYREG_PRT1_DR, buffer[laddress]);

I get only 255/FF back in the results. Is this something that doesn't work for PSoC4? Are there other approaches that will work with this MCU that can speed up port reads and writes?

paul.chambre_1977636's picture
User
44 posts

One other issue:

I added some logic in my TopDesign to NOR the CS and RW signals.This will go high only when I get a Write (low) while CS is enabled (low). I attached a rising edge interrupt to this and wrote a handler for it. I then modified my CS handler to enable the Write handler only after the address has been read and the data at the address location has been written to the data bus.

The problem I'm having is that, even if I leave the Write handler disabled forever, it still causes my data reads to return garbage. If I don't start it at all, I'm fine, though. I would have thought that a disabled handler and a never-started handler would incur the same timing costs, but that does not appear to be the case. Any idea what's happening here?

Update: I've found that this behavior changes if I move the Global Interrupt enable call to after the call where I start and disable the Write interrupt.

paul.chambre_1977636's picture
User
44 posts

And one last update for now. With the current (attached) version of the project, my HELLO WORLD read works, as many times as I want to run it, with the Write handler in place, and being enabled each time the address has been read... but, once I try to actually write any data (POKE to some address), read stops working, and instead gets 0 from each address. In other words, once the write interrupt gets triggered a first time, it breaks something in handling all subsequent reads.

I would guess that, other than just being weirdness, there is something I need to do to reset the interrupt state for Write, but I haven't found any options. ClearPending doesn't seem to make any difference.

The one encouraging point about this is that it does seem that the interrupt is getting triggered...

paul.chambre_1977636's picture
User
44 posts

I tried something different: I dropped the interrupt handling and instead added the function below to the FOR loop. Basically, I was finding a bunch of weird behavior with the interrupt handler... adding conditional logic further down would cause different behavior near the top.

With this function being called in the FOR loop, I can read and write data between the MCU and CPU. This is progress, but it's not ideal. The main issue I have with it is that this won't allow me to let the MCU sleep when idle. I read in one of the interrupt ANs that there is 16 clock cycles of overhead to calling an interrupt. I'm guessing that that's part of what I'm seeing and why this looped routine works. Any other suggestions on how I can make this work through an interrupt handler instead of a continuous loop?

void ProcessReq()
{
    if (!(CyPins_ReadPin(Pin_CS_0)))
    {
        //ReadAddress(); //lines below are what was in the ReadAddress function      
        laddress = Pin_Address_Low_Read();
        haddress = Pin_Address_High_Read();
        address = (haddress << 8) + laddress;    
        //Write date regardless... R/W signal will determine whether its pushed onto the bus
        Pin_Data_Write(buffer[laddress]);
        //CY_SET_REG8(CYREG_PRT1_DR, buffer[laddress]);
          
        while (!(CyPins_ReadPin(Pin_CS_0))) // && !read)
            if (!(CyPins_ReadPin(Pin_RW_0)))
            {
                buffer[laddress] = Pin_Data_Read();
            }
    }
}
 

paul.chambre_1977636's picture
User
44 posts

One last question on this thread: is there a way to clock and latch data into a PSOC 4 Pins array?

I have reliable write behavior implemented now in my project, but I'm limited to a 256 byte buffer to exchange data. This is because if I add anything else to the routine, like reading the upper half of the 16 bit address, it takes too long and I don't get the data off the data bus when the R/W line pulses low. I think that if I could use this pulse to clock and latch data into the data pins register, I could grab the data after the fact, instead of just during that narrow pulse.

By the way, I have tried a number of things, including multiple buffers, with mulitple DoBuffer functions, but even the switch/case statement (or an array of pointers to the functions) took too long to process.

 

user_1377889's picture
User
9606 posts

Did you already try the "Clocking" section of your pins component? There is the choice for "External" setting which will add an input  to the pin.

 

Bob

paul.chambre_1977636's picture
User
44 posts

I looked at that, but I didn't try anything with it because it's not completely documented. The datasheet doesn't say anything, for example, about which edge or state of the clock signal will bring data into the register, nor is there any information about why you would want to use the external clock, vs the clock_en, vs both.

user_1377889's picture
User
9606 posts

As usual the rising edge will clock the data into or out of the internal buffers. The datasheet is quite clear about the usage.

 

Bob

paul.chambre_1977636's picture
User
44 posts

OK. Thanks. Good to know.

I think I may not need it, though. I refactored the code to make most of the variables local and move most of the processing directly into main(), instead of in functions. It's not as clean, but it is more efficient. Between that, and a bit of optimization around how I read and combine the address parts, I now have code that seems fast enough to reliably read and write, even with a 1K (10-bit) buffer.

I think I'm ready to start writing some interface and back-end work functions.

 

Log in to post new comments.