Neo1973 GTA01B4: API para los timer PWM del s3c2410 (es)

Presentamos en este artículo la primera aportación práctica de kernel-labs.org al proyecto OpenMoko. La aportación ha consistido en dotar de soporte genérico a los timers PWM del microcontrolador, que dirige al teléfono Neo1973 y modificar algunos drivers, ya existentes, para el uso de este API genérico.

Los parches han sido aceptados por el líder técnico del proyecto,Harald Welte, por tanto, el equipo de kernel-labs.org puede considerarse en estos momentos como contribuidor voluntario del kernel Linux del proyecto OpenMoko.

Introducción

El enfoque del artículo es púramente técnico y conciso, no profundizaremos en ningún aspecto, pues el objetivo es proporcionar una descripción breve del desarrollo acometido. El objetivo del desarrollo ha sido crear un API genérico para los timer PWM del microcontrolador de Samsung. Con este API modificar dos drivers exsitentes, el driver encargado de la iluminación del LCD del Neo1973 y el driver que produce la vibración del móvil.

Procesador

La cabeza pensante del teléfono Neo1973 en su versión GTA01Bv4 es un microcontrolador SAMSUNG SoC Mobile S3C2410 RISC 16/32 bits. Es implementado con un core ARM920T RISC 16/32 bits. Entre otras cosas, se caracteriza por disponer de MMU, bus AMBA (Adavanced Microcontroller Bus Architecture), arquitectura de cache Hardvard con 16KB para instrucciones y 16KB para datos de cache, cada una con una palabra de 8 bits, etcétera.

Este microcontrolador (MCU) dispone de gran cantidad de controladores integrados, pero sólo algunos periféricos de los diponibles, nos interesan para este desarrollo:
  1. General Purpose Input/Output Ports (GPIO): 24 external interrupt ports, multiplexed input/output ports.
  2. Timers with Width Modulation (PWM): 4 canales de timer con PWM de 16 bits. Un canal de 16-bits de timer interno con operacion basada en DMA o basada en interrupciones. Programable duty-cycle, frecuencia y polaridad. Gerneración de Dead-zone. Soporte de fuentes de reloj externas, etc.
Existe soporte específico en el kernel Linux para esta familia de microcontroladores: Samsung-S3C24XX. No obstante, no existe código para el manejo adecuado de los timer con capacidades PWM, por ello el objetivo de este desarrollo. El mantenedor es el kernel hacker Ben Dooks. Será decisión de este último, incluir el código resultante para OpenMoko, en el código genérico que da soporte al S3c24XX en la rama principal del kernel Linux (Linux kernel mainstream).

GPIO: General Purpose Input/Output

El General Purpose Input/Output o Bus Expander, es una técnica hardware muy usada en microcontroladores que adecuadamente cableada por el diseño de la electrónica del componente y adecuadamente programada mediante software, permite el control de distintos componentes del sistema. Su objetivo es expandir los puertos de entrada y salida del microcontrolador. Se conectan los pines del GPIO a diversos componentes, como LEDs, timers, etc, y de esta forma un pin del GPIO puede ser usado como pin de entrada para leer un switch, otro puede ser usado como pin de salida para escribir en una EEPROM, para activar un LED. En definitiva, cualquier uso para escribir/leer en los componentes que el diseñador del hardware haya considerado. El S3C2410A tiene 117 puertos de E/S multifuncionales. Son los siguientes:
  • Port A (GPA): 23-output port
  • Port B (GPB): 11-input/output port
  • Port C (GPC): 16-input/output port
  • Port D (GPD): 16-input/output port
  • Port E (GPE): 16-input/output port
  • Port F (GPF): 8-input/output port
  • Port G (GPG): 16-input/output port
  • Port H (GPH): 11-input/output port
La asignación de puertos en el GTA01Bv4 la podemos encontar en el siguiente enlace: GTA01Bv4/gpio.txt

Especialmente nos iteresan el puerto GPIO GPB0 y el puerto GPB3, que son pines configurados para escribir en el controlador backlight del LCD del Neo1973, y para escribir en el controlador del motor de vibración, respectivamente.

PWM: Pulse Width Modulation

Como hemos dicho, el objetivo del desarrollo, es la creación de un API genérico para el uso de los timer con capacidad PWM del microcontrolador. De esta forma, este API puede ser usado por los drivers que necesiten configurar dichos timers, actualmente los drivers gta01-backlight y gta01-vibrator. Describimos a continuación que es el PWM o Modulación por Anchura de Pulsos.

Pulse Width Modulation (PWM) es una técnica usada para controlar circuitos analógicos con las salidas digitales de un procesador. Los circuitos analógicos presentan estados no discretos, tanto en valores como en el tiempo. Por ejemplo una batería de nueve voltios (9 V) raramente dará estados de nueve voltios, su valor cambiará con el tiempo y su rango de valores puede ser infinito, es decir, el conjunto de valores que puede presentar la señal analógica de la barería no es finito. Por el contrario las señales digitales siempre presentan un conjunto de valores predeterminado y finito, como por ejemplo 0 V o 5 V.

Los voltajes analógicos son con frecuencia usados para controlar elementos electrónicos directamente, como el volumen de un reproductor, la frecuencia de una emisora de radio analógica, etc. El esquema habitual es un selector conectado a un resistor que aumenta o disminuye la resistencia, de forma que el voltaje es aumentado o disminuido, presumiblemente aumentando o disminyendo el volumen. El volumen es el elemento electrónico analógico cuya salida es linealmente proporcional a la entrada.

Los circuitos analógicos suelen perder la precision (sus propiedades) con el tiempo y son muy vulnerables al ruido. Para lograr precisión es necesario circuitos analógicos de precisión que suelen ser muy caros y propensos a generar calor, que hacen necesario grandes disipadores.

Existe una solución que consiste en controlar dispositivos analógicos con señales digitales, que reducen el coste y el consumo de potencia al mínimo. Es habitual que los microcontroladores y DSP actuales tengan elementos digitales para tal propósito, son los PWM. Con un PWM se pueden codificar niveles de señal analógica digitalmente.

Mediante contadores de alta resolución el ciclo de servicio (duty cicle) de una onda cuadrada es modulado para codificar niveles de señal analógica específicos. El ciclo de servicio o rendimiento de cualquier forma de onda rectangular se refiere al porcentaje del ciclo de la señal que permanece alto, en lógica 1. Si la señal pasa la mitad de su tiempo en lógica 1 y la otra mitad en lógica 0, tenemos una forma de onda con un ciclo de servicio o rendimiento del 50%. Esto describiría una onda perfecta, una onda simétrica cuadrada.

El voltaje es proporcionado a la carga analógica mediante una serie de repetiones de pulsos ON y OFF (o pulsos en lógica 1 y 0). El tiempo del pulso en lógica 1 es el voltaje aplicado al dispositivo analógico, el tiempo en lógica negativa es el tiempo del voltaje a cero. Dado un ancho de banda adecuado se puede suministrar cualquier valor de voltaje analógico.

Nota: El PCLK: Processor Clock: Para la modulación del pulso se utilizan registros del PWM que permiten la división de la señal de pulso de referencia, que generalmente es la señal PCLK. El PCLK es una de las distintas señales de reloj internas derivadas del la señal de reloj principal que utiliza el MCU (microcontroller). El PCLK es utilizada por el bus y los subsistemas SPI, PWM, ATD0 y ATD1.Si la fuente de reloj (para un timer PWM, por ejemplo) es PCLK, es necesario programar el prescalerinterno para obtener con exactitud la frecuencia de trabajo. En función del bus del sistema se introduce a veces como una cifra en MHz, por ejemplo: (PCLK) a 2.45Mhz.

Los timer PWM del S3C2410

El MCU s3c2410 tiene cinco timers programables, 4 de ellos tienen la función PWM (timer0, timer1, timer2, timer3) , y el quinto (timer4) no tiene linea de salida, es para uso interno.

La labor del equipo de kernel-labs.org para este desarrollo, ha sido la habitual para el desarrollo de dispositivos empotrados: lectura exahustiva de la especificación del microcontrolador del fabricante. Hay que entender perfectamente el modo de operar del dispositivo en cuestion. Registros, bytes, palabras, DMAs, modos de operación son los elementos en juego para hacer funcionar el dispositivo; entender la especificación del fabricante no siempre es una tarea sencilla.

No profundizaremos en la especificación del fabricante, para lectores interesados pueden proceder a su descarga en: um_s3c2410a_rev11.pdf

Compilar el kernel para desarrollo

Brevemente enumeramos los pasos dados para perparar el entorno de desarrollo y la creación de la imagen del kernel para las pruebas.
  1. wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.22.5.tar.gz
  2. cd linux-2.6.22.5
  3. svn co https://svn.openmoko.org/trunk/src/target/kernel/patches
  4. quilt push -a
  5. wget http://svn.openmoko.org/trunk/oe/packages/linux/linux-gta01/defconfig-2.6.22.5-fic-gta01
  6. make ARCH=arm CROSS_COMPILE=$HOME/OM/moko/build/tmp/cross/bin/arm-angstrom-linux-gnueabi- vmlinux
  7. $HOME/OM/moko/build/tmp/cross/bin/arm-angstrom-linux-gnueabi-objcopy -O binary -R .note -R .comment -S vmlinux linux.bin
  8. gzip -9 linux.bin
  9. $HOME/OM/moko/build/tmp/work/armv4t-angstrom-linux-gnueabi/ u-boot-mkimage-openmoko-native-1.2.0+git9912121f7ed804ea58fd62f3f230b5dcfc357d88svn2238-r2/git/tools/mkimage -A arm -O linux -T kernel -C gzip -a 30008000 -e 30008000 -n "Kernel Image QT2410" -d linux.bin.gz uImage
  10. cu -l /dev/ttyACM0
  11. GTA01Bv4 # nand erase clean kernel
  12. $HOME/OM/moko/build/tmp/deploy/glibc/images/fic-gta01/dfu-util -a 3 -R -D ./uImage

El código

No entraremos en la descripción del código aportado y/o modificado, para no extendernos. Los parches se enumeran a continuación:
  1. s3c2410-pwm.patch - r3121: Parche con el API para el soporte de PWM.
  2. gta01-backlight.patch - r3137: Modificación del driver de retroiluminación para el uso del API anterior.
  3. gta01-vibrator.patch - r3137: Adaptación del driver del vibrador del Neo1973 para el uso de PWM, pues anteriormente sólo usaba la operación ON/OFF, apagado o plena vibración. Con esta modificación puede modularse la velocidad de vibración, además de usar el nuevo API genérico.
Se puede observar que los parches se refieren a una revisión concreta del repositorio de OpenMoko, esas fueron las aportaciones iniciales, actualmente dicho código ya ha recibido mejoras y modificaciones por otros integrantes de la comunidad OpenMoko.

Submitted by eleazar on Wed, 2010-03-24 18:14.

Gracias por la aportación, poco a poco esto va avanzando :-) ; mucha suerte.