Using mmap in C-Code from Linux application to access GPIOs. I want to control the GPIO PF4 on the STM32MP1 with mmap() due to speed requirements, but the pin is not toggling.
Details:
HW: Phytec Sargas Board, which is similar to the STM32MP1-DK2.
Build environment: Cross compiling with SDK generated by Yocto.
Linux: Yocto build, based on st-image weston.
Device Tree configuration: As far as I understood not needed to access single GPIOs.
Any help is appreciated :)
Code (only partially):
#define MEM_DEV "/dev/mem"
#define GPIOF_START_ADDR 0x50007000
#define GPIOF_END_ADDR 0x500073FF
#define GPIOF_MAP_SIZE (GPIOF_END_ADDR - GPIOF_START_ADDR)
#define GPIO_REG_MODER 0x00 /**< GPIO port mode register */
#define GPIO_REG_OTYPER 0x04 /**< GPIO port output type register */
#define GPIO_REG_BSRR 0x18 /**< GPIO port bit set/reset register */
#define GPIO_PIN_4 ((uint16_t)0x0010U)
#define GPIO_PIN_OUTPUT_DIRECTION 0x01 /**< Output */
#define GPIO_PIN_OUTPUT_PUSHPULL 0x00 /**< Output Push Pull Mode */
int main(int argc, char **argv)
{
int ret = EXIT_SUCCESS;
static void *mmapBase = NULL; /* Virtual base address */
signal(SIGINT, intHandler); /* Catch CTRL + C signal*/
signal(SIGTERM, intHandler); /* Catch kill signal */
/* Try to open the mem device special file */
int fdMem = open(MEM_DEV, O_RDWR | O_SYNC);
if (fdMem < 1)
{
exit(1);
}
/* Map memory region for the gpio registers */
mmapBase = mmap(NULL,
GPIOF_MAP_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fdMem,
GPIOF_START_ADDR);
if (mmapBase == (void*) -1)
{
exit(1);
}
{ /* MODER */
/* Load the different gpio register pointers with its address */
volatile uint32_t *gpioRegAddr = mmapBase + GPIO_REG_MODER;
/* Get the value of the gpio direction register */
uint32_t gpioRegVal = *gpioRegAddr;
/* Clear the GPIO, write it back to the direction register */
gpioRegVal &= ~(0x03 << (4 * 2)); /* mask out the 2 bits giving the direction */
gpioRegVal |= ((GPIO_PIN_OUTPUT_DIRECTION) << (4 * 2));
*gpioRegAddr = gpioRegVal;
}
{ /* OTYPE */
/* Load the different gpio register pointers with its address */
volatile uint32_t *gpioRegAddr = mmapBase + GPIO_REG_OTYPER;
/* Get the value of the gpio direction register */
uint32_t gpioRegVal = *gpioRegAddr;
/* Clear the GPIO, write it back to the direction register */
gpioRegVal &= ~(0x0 << (4)); /* mask out */
gpioRegVal |= ((GPIO_PIN_OUTPUT_PUSHPULL) << (4));
*gpioRegAddr = gpioRegVal;
}
volatile uint32_t *const gpioSetClearDataOutAddr = mmapBase + GPIO_REG_BSRR;
keepRunning = 1;
while(keepRunning)
{
*gpioSetClearDataOutAddr = GPIO_PIN_4_REG_DEFINITION; /* set the pin */
sleep_ms(500);
*gpioSetClearDataOutAddr = (uint32_t)(GPIO_PIN_4_REG_DEFINITION << 16); /* reset the pin */
sleep_ms(500);
}
return ret;
}