En esta ocasión indicaré los pasos que seguí para habilitar el módulo SPI en el espacio de usuario, en Olinuxino A20 Micro, con un kernel mainline compilado por mi (los detalles para compilar tu propio kernel los daré posteriormente).
IMPORTANTE antes de continuar:
Esta guía requiere que tengas nociones de programación, y experiencia compilando el kernel Linux.
Es necesario que dispongas del código fuente de Linux, descarga el código desde el repositorio de tu preferencia, recomiendo la última versión estable (a la fecha la 4.9.30, ya que las versiones anteriores tienen problemas con el controlador Ethernet).
Primer paso (Reconocer el hardware): Lo más probable es que hayas comprobado que tu módulo SPI no está disponible en el espacio de usuario, es decir, si ejecutas
ls /dev/spi*
el comando no encontrará ningún dispositivo SPI, caso contrario aparecerá algo similar a esto:
/dev/spidev1.0
/dev/spidev1.1
El driver del kernel asigna los nombres spidevX.Y a los buses SPI que se encuentren configurados, siendo X el numero de puerto (del alias, no del puerto físico, esto será aclarado posteriormente), es decir:
SPI1 = spidev0.Y
SPI2 = spidev1.Y
el valor Y viene a ser el índice del dispositivo colgado al bus, por ejemplo, tenemos dos dispositivos conectados al puerto SPI2, cada uno de ellos con su propia línea de chip select csY, entonces:
dispositivo 1: (cs0) = spidev1.0
dispositivo 2: (cs1) = spidev1.1
La siguiente imagen muestra los puertos disponibles en el Olinuxino A20
Entonces, por ejemplo, mi aplicación utiliza dos dispositivos SPI, los cuales he conectado en el GPIO-3, en los pines
- SPI2-CS1 -> 24 - PB13
- SPI2-CS0 -> 26 - PB14
- SPI2-CLK -> 28 - PB15
- SPI2-MOSI -> 30 - PB16
- SPI2-MISO -> 32 - PB17
Segundo paso (Definir el hardware):
Ahora vamos a habilitar el módulo dentro del árbol de dispositivos, el cual es un archivo que define la estructura de hardware del dispositivo, el driver usa ésta información para permitir el acceso a los buses tal y como indiqué anteriormente; para esto vamos a sacar una copia de respaldo y a editar el siguiente archivo:
cp RUTA_DEL_CODIGO/arch/arm/boot/dts/sun7i-a20-olinuxino-micro.dts RUTA_DEL_CODIGO/arch/arm/boot/dts/sun7i-a20-olinuxino-micro-original.dts
Abrimos el archivo sun7i-a20-olinuxino-micro.dts, el cual viene por defecto con la siguiente configuración del SPI:
&spi2 {
pinctrl-names = "default";
pinctrl-0 = <&spi2_pins_a>,
<&spi2_cs0_pins_a>;
status = "okay";
};
Y hacemos el cambio para configurar nuestros dispositivos:
&spi2 {
pinctrl-names = "default";pinctrl-0 = <&spi2_pins_b>,
<&spi2_cs0_pins_b>, <&spi2_cs1_pins_a>; status = "okay"; spi2_0 { #address-cells = <1>; #size-cells = <0>; compatible = "spidev";
reg = <0>;
spi-max-frequency = <50000000>;
};
spi2_1 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "spidev";
reg = <1>;
spi-max-frequency = <50000000>;
};
};
El índice del dispositivo será reg = <Y>;
En estas líneas estamos activando los dispositivos para el espacio de usuarios, es decir, ahora podemos abrir el SPI accediendo a su respectivo /dev/spidevX.Y, aquí se crean los alias.
Ahora es necesario también editar el archivo sun7i-a20.dtsi el cual originalmente viene con el siguiente fragmento de código:
Analizando este fragmento de código, nos podemos dar cuenta que nuestro dispositivo puede utilizar la configuración spi2_pins_b con spi2_cs0_pins_b, pero no disponemos del segundo chip select que requerimos, el cual está conectado a PB13, entonces necesitamos agregar ésta opción, mediante el siguiente fragmento de código:
spi2_pins_a: spi2@0 {
allwinner,pins = "PC20", "PC21", "PC22";
allwinner,function = "spi2";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
spi2_pins_b: spi2@1 {
allwinner,pins = "PB15", "PB16", "PB17";
allwinner,function = "spi2";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
spi2_cs0_pins_a: spi2_cs0@0 {
allwinner,pins = "PC19";
allwinner,function = "spi2";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
spi2_cs0_pins_b: spi2_cs0@1 {
allwinner,pins = "PB14";
allwinner,function = "spi2";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
Analizando este fragmento de código, nos podemos dar cuenta que nuestro dispositivo puede utilizar la configuración spi2_pins_b con spi2_cs0_pins_b, pero no disponemos del segundo chip select que requerimos, el cual está conectado a PB13, entonces necesitamos agregar ésta opción, mediante el siguiente fragmento de código:
spi2_cs1_pins_a: spi2_cs1@0 {
allwinner,pins = "PB13";
allwinner,function = "spi2";
allwinner,drive = <SUN4I_PINCTRL_10_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
Con este cambio ahora las opciones de pines son spi2_pins_b, spi2_cs0_pins_b además de spi2_cs1_pins_a (que fue agregado en este último paso), y por ésta razón se seleccionan estos pines en el archivo sun7i-a20-olinuxino-micro.dts.
Ahora, para que todo esto funcione, es necesario que el driver SPI tenga habilitada la opción para uso en el espacio de usuarios, para esto es necesario configurar el código fuente y compilarlo.
Tercer paso (Habilitación del driver en el kernel):
Accedemos al menú de configuración del kernel ejecutando:
make ARCH=arm CROSS_COMPILE=/RUTA/DE/TU/COMPILADOR/arm-linux-gnueabihf- menuconfig
Activar la opción para que sea compilada en el kernel y no como modulo:
- Device Drivers --->
- SPI support --->
- User mode SPI device driver support
Realizar las configuraciones que se requieran y guardarlas, para luego ejecutar:
La opción j4 índica el número de núcleos usados para la compilación, depende de tu procesador, donde 4 indica 4 núcleos.
Luego se ejecuta:
make ARCH=arm CROSS_COMPILE=/RUTA/DE/TU/COMPILADOR/arm-linux-gnueabihf- INSTALL_MOD_PATH=output -j4 modules_install
Esto para compilar e instalar los módulos en la ubicación output dentro de la ubicación donde estés compilando el código, y posteriormente copiar los archivos generados en la compilación y sustituirlos por los que tengas en tu dispositivo.
No hay comentarios.:
Publicar un comentario