Switching port from output to input and not getting correct input data

I'm using port P2 on a RF100MF as both output for writing an address and input for data. It also have pins for ALE (Address Latch Enable), READ and WRITE.

However when reading the port it just returns the address I wrote.

My code:

// ALE=1 & high address
P0 = _10_Pn4_OUTPUT_1 | _20_Pn5_OUTPUT_1 | _40_Pn6_OUTPUT_1 | addr_high;
// low address
P2 = addr_low;
// >10 nS
NOP();
// ALE=0
P0 &= ~_10_Pn4_OUTPUT_1;
// >20 nS
NOP();
// AD0-7 as input
PM2 = _01_PMn0_MODE_INPUT | _02_PMn1_MODE_INPUT | _04_PMn2_MODE_INPUT | _08_PMn3_MODE_INPUT |
_10_PMn4_MODE_INPUT | _20_PMn5_MODE_INPUT | _40_PMn6_MODE_INPUT | _80_PMn7_MODE_INPUT;
// RD=0
P0 &= ~_40_Pn6_OUTPUT_1;
P2 = 0x00;
// >115 nS
NOP();
NOP();
NOP();
// Read data
data = P2;
// RD=1
P0 |= _40_Pn6_OUTPUT_1;
// AD0-7 as output
PM2 = _00_PMn0_MODE_OUTPUT | _00_PMn1_MODE_OUTPUT | _00_PMn2_MODE_OUTPUT | _00_PMn3_MODE_OUTPUT |
_00_PMn4_MODE_OUTPUT | _00_PMn5_MODE_OUTPUT | _00_PMn6_MODE_OUTPUT | _00_PMn7_MODE_OUTPUT;

I'm trying to read address 0x16 from the external chip which should result in data being 0x9A, but I just get 0x16. On my oscilloscope I can see the input pins are as expected:

The assembler code produced by the IAR compiler also looks correct:

85 // ALE=1 & high address
86 P0 = _10_Pn4_OUTPUT_1 | _20_Pn5_OUTPUT_1 | _40_Pn6_OUTPUT_1 | addr_high;
\ 00001D 60 MOV A, X ;; 1 cycle
\ 00001E 6C 70 OR A, #0x70 ;; 1 cycle
\ 000020 9D 00 MOV S:0xFFF00, A ;; 1 cycle
87 // low address
88 P2 = addr_low;
\ 000022 8B61 XCH A, B ;; 1 cycle
\ 000024 9D 02 MOV S:0xFFF02, A ;; 1 cycle
\ 000026 8B61 XCH A, B ;; 1 cycle
89 // >10 nS
90 NOP();
\ 000028 00 NOP ;; 1 cycle
91 // ALE=0
92 P0 &= ~_10_Pn4_OUTPUT_1;
\ 000029 4371 00 CLR1 S:0xFFF00.4 ;; 2 cycles
93 // >20 nS
94 NOP();
\ 00002C 00 NOP ;; 1 cycle
95 // AD0-7 as input
96 PM2 = _01_PMn0_MODE_INPUT | _02_PMn1_MODE_INPUT | _04_PMn2_MODE_INPUT | _08_PMn3_MODE_INPUT |
97 _10_PMn4_MODE_INPUT | _20_PMn5_MODE_INPUT | _40_PMn6_MODE_INPUT | _80_PMn7_MODE_INPUT;
\ 00002D CE 22 FF MOV 0xFFF22, #0xFF ;; 1 cycle
98 // RD=0
99 P0 &= ~_40_Pn6_OUTPUT_1;
\ 000030 6371 00 CLR1 S:0xFFF00.6 ;; 2 cycles
100 // >115 nS
101 NOP();
\ 000033 00 NOP ;; 1 cycle
102 NOP();
\ 000034 00 NOP ;; 1 cycle
103 NOP();
\ 000035 00 NOP ;; 1 cycle
104 // Read data
105 data = P2;
\ 000036 8D 02 MOV A, S:0xFFF02 ;; 1 cycle
\ 000038 98 00 MOV [SP], A ;; 1 cycle
106 // RD=1
107 P0 |= _40_Pn6_OUTPUT_1;
\ 00003A 6271 00 SET1 S:0xFFF00.6 ;; 2 cycles
108 // AD0-7 as output
109 PM2 = _00_PMn0_MODE_OUTPUT | _00_PMn1_MODE_OUTPUT | _00_PMn2_MODE_OUTPUT | _00_PMn3_MODE_OUTPUT |
110 _00_PMn4_MODE_OUTPUT | _00_PMn5_MODE_OUTPUT | _00_PMn6_MODE_OUTPUT | _00_PMn7_MODE_OUTPUT;
\ 00003D CE 22 00 MOV 0xFFF22, #0x0 ;; 1 cycle

Anyone know what I'm missing?

Thanks!

/Thomas

  • I tried creating a new project using Applilet3 for my QB-R5F100LE-TB board and adding the code below to main().

    But I still just get the data back that I wrote to the port. In this case I should get 0x00 as nothing is connected to the pins.

    /* Start user code. Do not edit comment generated here */
    volatile uint8_t data = 0;
    while (1U)
    {
    #define addr_low 0x16
    #define addr_high 0x00

    // ALE=1 & high address
    P0 = _10_Pn4_OUTPUT_1 | _20_Pn5_OUTPUT_1 | _40_Pn6_OUTPUT_1 | addr_high;
    // low address
    P2 = addr_low;
    // >10 nS
    NOP();
    // ALE=0
    P0 &= ~_10_Pn4_OUTPUT_1;
    // >20 nS
    NOP();
    // AD0-7 as input
    PM2 = _01_PMn0_MODE_INPUT | _02_PMn1_MODE_INPUT | _04_PMn2_MODE_INPUT | _08_PMn3_MODE_INPUT |
    _10_PMn4_MODE_INPUT | _20_PMn5_MODE_INPUT | _40_PMn6_MODE_INPUT | _80_PMn7_MODE_INPUT;
    // RD=0
    P0 &= ~_40_Pn6_OUTPUT_1;
    // >115 nS
    NOP();
    NOP();
    NOP();
    // Read data
    data = P2;
    // RD=1
    P0 |= _40_Pn6_OUTPUT_1;
    NOP();
    // AD0-7 as output
    PM2 = _00_PMn0_MODE_OUTPUT | _00_PMn1_MODE_OUTPUT | _00_PMn2_MODE_OUTPUT | _00_PMn3_MODE_OUTPUT |
    _00_PMn4_MODE_OUTPUT | _00_PMn5_MODE_OUTPUT | _00_PMn6_MODE_OUTPUT | _00_PMn7_MODE_OUTPUT;
    NOP();
    }
    /* End user code. Do not edit comment generated here */

  • In reply to ThomasDamgaard:

    Hi Thomas,

    Have you solved this already? What external device are you trying to read?

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-us.knowledgebase.renesas.com/

  • In reply to JB:

    Hi JB,
    No. I haven't.
    It's a profibus chip, SPC3, but it seems to be unrelated to the external chip as I have the same issue with my demo board with nothing connected...
    BR, Thomas
  • In reply to ThomasDamgaard:

    If nothing is connected to the pins, why should you then read 0x00?
    The output data charges parasitic capacitors in the port circuit, and a read of the port shortly after an data output will return exactly what you see, the output data. In order to read 0x00 you have to attache poull-down resistors on all pins.
  • In reply to FrankL:

    It doesn't matter how long I wait, I still read the same. And for my own board I can measure it's not what's on the pins...
    BR, Thomas
  • In reply to ThomasDamgaard:

    Have you tried to put a break in the read function and read the port register in the debugger?
  • In reply to FrankL:

    Yes. They also say 0x16.
    BR, Thomas
  • In reply to FrankL:

    I am facing same problem.
    I am using P16 of R5F102AA (RL78/G12 MCU) as both input and output.
    If I keep P16 as input always, the pin value read works.
    if I switch P16 to output and back to input, the P16 value is always the old value.

    I am using e2 studio and code generator.
    I switch P16 to output by setting PM1 = _00_PMn6_MODE_OUTPUT
    I switch P16 to input by settting PM1 = _40_PMn6_MODE_INPUT

    I tried adding delay (10000 NOPs), enable and disabling pull up. Nothing works.

    Any help?
  • In reply to Elango:

    Surprisingly, enabling TTL Buffer for P16 pin allows it to read the value.
    But there are other pins without TTL buffer also. They still don't work. I need to use them too.
  • In reply to Elango:

    Thanks, Elango. I haven't tried that. The pins we're using don't have that option, but I maybe I can try it on some other pins.

    Could someone from Renesas comment on this? How is this supposed to work? I can't see in the datasheets that switching between input and output is somehow limited.