欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

LS1046ACPU ARM架构点灯小程序

程序员文章站 2022-06-20 21:02:10
...
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h> 

#define OK          0
#define ERROR       -1

#define GPIO1_BASE_PHY_ADDR 0x2300000
#define GPIO_GROUP_SIZE     0x10000


#define GPDIR_OFFSET 0x0
#define GPODR_OFFSET 0x4
#define GPDAT_OFFSET 0x8


#define GPIO_DIR_IN 0
#define GPIO_DIR_OUT 1

static void *gpio_vir_base_addr = NULL;


void *phy_addr_to_virt(int32_t phy_base_addr, int32_t size)
{
    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    if(fd < 0)
        return NULL;
    void *virt_addr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, phy_base_addr);
    close(fd);
    return virt_addr;
}

uint32_t set_bit_to_high(int32_t pin_num)
{
    uint32_t mask = (uint32_t)(1U << (31 - pin_num));
    return mask;
}

uint32_t set_bit_to_low(int32_t pin_num)
{
    uint32_t mask = (uint32_t)(1U << (31 - pin_num));
    return ~mask;
}

int32_t led_on(int32_t group, int32_t pin_num)
{
    uint64_t addr = (group - 1) * GPIO_GROUP_SIZE + GPDAT_OFFSET + gpio_vir_base_addr;
    uint32_t mask = set_bit_to_low(pin_num);
    uint32_t src = (ntohl)(*(volatile uint32_t *)addr);
    uint32_t dst = src & mask;
    *(volatile uint32_t *)addr = (htonl)(dst);
    return OK;
}

int32_t led_off(int32_t group, int32_t pin_num)
{
    uint64_t addr = (group - 1) * GPIO_GROUP_SIZE + GPDAT_OFFSET + gpio_vir_base_addr;
    uint32_t mask = (set_bit_to_high(pin_num));
    uint32_t src = (ntohl)(*(volatile uint32_t *)addr);
    uint32_t dst = src | mask;
    *(volatile uint32_t *)addr = (htonl)(dst);
    return OK;
}

int32_t gpio_dir_set(int32_t group, int32_t pin_num, int32_t dir)
{
    uint64_t addr = (group - 1) * GPIO_GROUP_SIZE + GPDIR_OFFSET + gpio_vir_base_addr;
    uint32_t src = (ntohl)(*(volatile uint32_t *)addr);
    if(dir == GPIO_DIR_OUT){
        *(volatile uint32_t *)addr = (htonl)(set_bit_to_high(pin_num) | src);
    }
    else if(dir == GPIO_DIR_IN){
        *(volatile uint32_t *)addr = (htonl)(set_bit_to_low(pin_num));
    }
    else
        return ERROR;
    return OK;
}

int32_t gpio_dir_get(int32_t group, int32_t pin_num)
{
    uint64_t addr = (group - 1) * GPIO_GROUP_SIZE + GPDIR_OFFSET + gpio_vir_base_addr;
    uint32_t src = (ntohl)(*(volatile uint32_t *)addr);
    /*未来得及测试*/
    return OK;
}


void gpio_test()
{
    int32_t i = 20;
    gpio_vir_base_addr = phy_addr_to_virt(GPIO1_BASE_PHY_ADDR, GPIO_GROUP_SIZE * 4);
    printf("gpio_vir_base_addr %#lx\n", gpio_vir_base_addr);
    if(gpio_vir_base_addr == NULL)
        printf("mmap error\n");
    
    gpio_dir_set(3, 15, GPIO_DIR_OUT);
    while(i-- > 0){
        led_on(3, 15);
        usleep(100000);
        led_off(3,15);
        usleep(100000);
    }
}

相关标签: 点灯 mmap