Софт процессор Nios II - Часть 3 - PIO

Собственно PIO, они же GPIO позволяют получить простой доступ к пользовательской логике или внешним устройствам, когда скорости bit banging более чем хватает. Как и порты AVR их можно использовать для :
  • контроля светодиодов
  • снятия данных с переключателей
  • управление дисплеями и пр.
Каждое ядро PIO может иметь от 1 до 32 I/O портов. И до 4х регистров : data, direction, interrputmask и edgecapture. 

Пример использования PIO



Порты I/O могут быть подключены к логике внутри и снаружи чипа, сконфигурированы на вход, выход, вход-выход с Z-состоянием. Регистры чтения-записи абсолютно независимы.

Ядра PIO могут быть сконфигурированы для захвата фронтов в портах ( с непривычки необычно : в AVR портом называется 8 пинов, в Nios2 - один пин ). Возможно фиксировать переход 1 - 0, 0 - 1 или оба. Когда на входе детектируется фронт, состояние детектируется в регистре edgecapture.

Прерывания. Ядро PIO может быть сконфигурировано для генерирования прерывания по фронту или спаду ( 1 или 0), для каждого порта имеется индивидуальная маска для активации генерирования прерывания.

Вся работа с PIO сопровождается файлом altera_avalon_pio_regs.h . Содержание файла :


#ifndef
 __ALTERA_AVALON_PIO_REGS_H__
#define __ALTERA_AVALON_PIO_REGS_H__ 

#include <io.h>
#define IOADDR_ALTERA_AVALON_PIO_DATA(base) __IO_CALC_ADDRESS_NATIVE(base, 0)
#define IORD_ALTERA_AVALON_PIO_DATA(base) IORD(base, 0)
#define IOWR_ALTERA_AVALON_PIO_DATA(base, data) IOWR(base, 0, data)
#define IOADDR_ALTERA_AVALON_PIO_DIRECTION(base) __IO_CALC_ADDRESS_NATIVE(base, 1)

#define IORD_ALTERA_AVALON_PIO_DIRECTION(base) IORD(base, 1)
#define IOWR_ALTERA_AVALON_PIO_DIRECTION(base, data) IOWR(base, 1, data)
#define IOADDR_ALTERA_AVALON_PIO_IRQ_MASK(base)__IO_CALC_ADDRESS_NATIVE(base, 2)

#define IORD_ALTERA_AVALON_PIO_IRQ_MASK(base) IORD(base, 2)
#define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base, data) IOWR(base, 2, data)
#define IOADDR_ALTERA_AVALON_PIO_EDGE_CAP(base) __IO_CALC_ADDRESS_NATIVE(base, 3)

#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base) IORD(base, 3)
#define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base, data) IOWR(base, 3, data)

#endif /* __ALTERA_AVALON_PIO_REGS_H__ */


Простейший код hello word будет выглядеть так :

/* *
PIO test
* */

#include <stdio.h>
#include <unistd.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"

int main()
{
int in, out;

while (1)
{
in = IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE);
out = in;
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, out);
}
}

Вот и всё. Полное качественное описание можно получить здесь : http://www.naliwator.narod.ru/ip_PIO.pdf

Комментарии