GPIO pins pull_up issue in HIFIVE 1 REV B

Hi everyone, most of the GPIO pins work fine with me as output. However, some pins when used as input it is always in pull up mode even if I put zero in the crossbanding pull up register. for example, pin 0, 1, 6 always pull up. PIN 12, 16 always pull down even if I put one in the crossbanding bit in the pull-up register. this table is not 100% accurate. if anyone can help or tell me who I should ask, I will be so thankful. Thanks in advance.

Could it be that those pins in question have been set to their IOF function? Look at the bits of IOF_EN (0x10012038): L=gpio, H=hw. Paragraph section 17.8 (page 77 of the FE310-G002 Manual) mentions that the IOF mode takes over control of all pin parameters – except for XOR control. See Figure 9 (page 75) and Table 53 (page 78).

When switching between input and output for a particular pin in gpio mode, it might be a good practice to disable the output before enabling the input, especially when the input pullup is enabled and the output drive strength is set to large (i.e., ‘1’ or 20ma). In other words, clear the bit of OUTPUT_EN (0x10012008) before setting the bit of INPUT_EN (0x10012004).

Note that missing from Table 52 of the manual are the following two fields:
GPIO_IOF_EN 0x10012038
GPIO_IOF_SEL 0x1001203C

Thanks very much for your response. it took me a while until I got the IOF address from fe310_g000.pdf. I feel there is a lot of things they should add to the datasheet. Also, I do exactly as you mentioned this is why I do not understand what is wrong. Also, if I used pins as pull up it work more than fine. Also, tell me if you like the way I initialize the pins and if there is a better way. Also, hopefully, you or anyone else could work with me to solve this issue. if you have any questions regarding my code please ask. thanks very much.



map

nice code, clever and clean way to represent a read-modify-write(1) paradigm in a single line. I like it.

Don’t understand what you mean by crossband/crossbond, but it’s okay.
Could there be a typo in your input_en function, should the '|' instead be an '&'?
image

At any rate, try grouping your input_en and output_en into two pairs, one for creating input pins and other for creating output pins. instead of EN, make a #define for IN and another for OUT, to clearly show the direction of the pin.

For example, with your F_0_7, to make pins be inputs, first make sure they’re not outputs:

*output_en = ((*output_en) & (~(PINS_IN_F_0_7 << 16)));
*input_en = ((*input_en) | ( (PINS_IN_F_0_7 << 16)));

Likewise, to make pins be outputs, first make sure they’re not inputs:

*input_en = ((*input_en) & (~(PINS_OUT_F_0_7 << 16)));
*output_en = ((*output_en) | ( (PINS_OUT_F_0_7 << 16)));

Where, for example, you might set the upper four bits to be inputs and lower four bits to be outputs

#define PINS_IN_F_0_7 0b11110000
#define PINS_OUT_F_0_7 0b00001111

and similarly for your other F’s.

Some of the io pins on HiFive1 Rev B might be connected to other devices, such as gpio_9 (your F_15) to a pullup resistor R10 when jumper SJ1 is soldered; and gpio_10 (your F_16) to another device’s output pin when jumper SJ2 is soldered. You might want to carefully check the schematic of the board to make sure.

Just make sure to keep all your IOF_EN pins set to all 0b0… and you should be fine.

-----
(1) When you’re concerned with atomicity, riscv offers a easy way to handle this using assembly instructions amoand, amoor, and amoxor for single operations; and a conjugate pair of instructions lr and sc when more than one operation, such as mask and set, are necessary.

1 Like

Thanks very much again for your respond. // 8 pins from 0 to 7 in the HIFIVe corresponding to offset 16 to 23 in the registers. 1 means the pin will be used as output 0 means it is used as input. this what I meant to write. sorry I miss wrote the word corresponding. Also, output_en = ((output_en ) &(~(0xff<<16))) |(PINS_EN_F_0_7 <<16) ; . first I clear the bits that I want to write to than I use | ,or , with the value that I want to write. I tried the way you said but it did not work out. what confuse me more, that pins work very good if I used them as pull up by putting 1 in the pull up register. I will keep trying. thanks very much again for your help.

I was having a small mistake in the way of initializing input_en. I fixed it but this was not the issue. I debug the program and directly after I enable the input pin there are values written in the input value register. I attached a picture. so why this value is written. thanks in advance.