Hi.
I am trying to configure SPI0 module through mmap.
I know that there is a library designed specifically for SPI module. The reason to use mmap is that I need to configure some aspects of this module for my project that can not be configured using IOCTL library.
To be more concise, I need to keep the clock running constantly, in order to have a system clock for the slave. I don´t know even it is possible, but I have been reading ARM335x Technical Reference Manual, and it seem that modifying SYSCONFIG module, it will be possible.
Here is the code that I am using:
HEADER FILE
#ifndef _SPI_register_H_ #define _SPI_register_H_ // mmap McSPI0 Registers. Base Address #define MCSPI0_START_ADDR 0x48030000 #define MCSPI0_END_ADDR 0x48031FFF #define MCSPI0_SIZE (MCSPI0_END_ADDR - MCSPI0_START_ADDR) // Offsets #define MCSPI0_SYSCONFIG 0x110 #define MCSPI0_MODULCTRL 0x128 #define MCSPI0_CH0CONF 0x12C #define MCSPI0_CDAFRX 0x1A0 #endif
SOURCE FILE
#include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include "SPI_register.h" #include <stdint.h> #include <unistd.h> #include <getopt.h> #include <linux/types.h> #include <linux/spi/spidev.h> int main(int argc, char *argv[]) { volatile void *spi0_addr = NULL; volatile unsigned int *spi0_sysconf_addr = NULL; static const char *device = "/dev/spidev1.0"; unsigned int reg; int fd = open("/dev/mem", O_RDWR); printf("Mapping %X - %X (size: %X)\n", MCSPI0_START_ADDR, MCSPI0_END_ADDR, MCSPI0_SIZE ); spi0_addr = mmap(0, MCSPI0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,MCSPI0_START_ADDR); // now spi0_addr is pointing at base address if(spi0_addr == MAP_FAILED) { printf("Unable to map SPI\n"); exit(1); } spi0_sysconf_addr = spi0_addr + MCSPI0_SYSCONFIG; // now it is pointing at the target address printf("SPI mapped to %p\n", spi0_addr); printf("SPI sysconf mapped to %p\n", spi0_sysconf_addr); // UNTIL HERE EVERYTHING WORKS PROPERLY reg = *spi0_sysconf_addr; printf("SPI sys configuration: 0x%X\n", reg); close(fd); return 0; }
As I have written in the source code, all the mapping process works. The problem arises when I trey to read one of those registers. It appears a bus error (SIGBUS)... I have thought that maybe bus clock is disabled...but I don´t know if I am right and how to fix this problem.
Is it possible that Linux does not allow me to access by this random way?
The think is that I have use exactly the same process to handle GPIOs and everything works perfectly.
I hope that you could help me.
Best regards,
Pablo