Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SPI: DM365 and VITA1300
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
/dev/null
Доброго дня!
Необходимо по SPI управлять матрицей VITA1300, на плате стоит процессор DM365, используется linux-2.6.18.
Технические особенности SPI на устройствах:
DM365: сдвиговый регистр 16 бит
VITA1300: адрес 9 бит, данные 16 бит
В качестве программы используется пример идущий в составе ядра.
Чтение регистра:
CODE
uint8_t tx[] = {0, 8};
uint8_t rx[ARRAY_SIZE(tx)] = {0, 0};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = 26,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);

Запись в регистр:
CODE
uint8_t trv[] = {1, 8};
uint8_t twv[] = {7, 9};
struct spi_ioc_transfer wr[2] = {
[0] = {
.tx_buf = (unsigned long)trv,
.rx_buf = (unsigned long)NULL,//rx,
.len = ARRAY_SIZE(trv),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = 10
},
[1] = {
.tx_buf = (unsigned long)twv,
.rx_buf = (unsigned long)NULL,//rx,
.len = ARRAY_SIZE(twv),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = 16
}
};
ret = ioctl(fd, SPI_IOC_MESSAGE(2), wr);

К чтению вопросов нет, возвращаемые значения соответствуют указанным в документации.
А вот с записью проблема, сама команда проходит без ошибок, но следующая команда чтения возвращает не изменённое значение.
В драйвер были вставлены отладочные сообщения, вывод следующий:
CODE
starting davinci_spi_setup
davinci_spi_setup_transfer: bits_per_word 8, hz 2500000
davinci_spi_setup_transfer: bits_per_word 8
starting davinci_spi_setup
davinci_spi_setup_transfer: bits_per_word 8, hz 2500000
davinci_spi_setup_transfer: bits_per_word 8
starting spidev_message
txbuf: [0] 0, [1davinci_spi_setup_transfer: bits_per_word 8, hz 2500000
] 0x8
davinci_spi_setup_transfer: bits_per_word 10
davinci_spi_chipselect: value 1
starting davinci_spi_bufs_pio
davinci_spi_bufs_pio, conv 2, count 1, len 2
starting davinci_spi_bufs_prep
davinci_spi_bufs_pio: data1_reg_val 268435456, cs_hold 1 << chhold_shift 28,
davinci_spi_bufs_pio: t->tx_buf
davinci_spi_bufs_pio: SPIINT 0x0, SPIFLG 0x1000200
#############################
davinci_spi_tx_buf_u16: tx 0x801
davinci_spi_bufs_pio, bits_per_word 8
davinci_spi_bufs_pio: data1_reg_val |= (mask & tx_data) 0x10fe0801 |= (0xFFFF & 0x801)
davinci_spi_bufs_pio: buf_val 0x80ff00c0
davinci_spi_bufs_pio: SPIFMT0 val 0x300a
davinci_spi_bufs_pio: SPIFMT1 val 0x300a
davinci_spi_bufs_pio: SPIFMT2 val 0x300a
davinci_spi_bufs_pio: SPIFMT3 val 0x300a
davinci_spi_bufs_pio: buf_val 0x80ff00c0 & SPI_SPIBUF_TXFULL_MASK 0x20000000 = 0x0
davinci_spi_bufs_pio: SPIFLG 0x1000200, count 0
#######################
davinci_spi_bufs_pio: int_status 0x1000200
starting davinci_spi_check_error
davinci_spi_check_error: ret 0
davinci_spi_bufs_pio: davinci_spi->count 2, t->len 2
davinci_spi_setup_transfer: bits_per_word 8, hz 2500000
davinci_spi_setup_transfer: bits_per_word 16
starting davinci_spi_bufs_pio
davinci_spi_bufs_pio, conv 2, count 1, len 2
starting davinci_spi_bufs_prep
davinci_spi_bufs_pio: data1_reg_val 268435456, cs_hold 1 << chhold_shift 28,
davinci_spi_bufs_pio: t->tx_buf
davinci_spi_bufs_pio: SPIINT 0x0, SPIFLG 0x1000200
#############################
davinci_spi_tx_buf_u16: tx 0x907
davinci_spi_bufs_pio, bits_per_word 8
davinci_spi_bufs_pio: data1_reg_val |= (mask & tx_data) 0x10fe0907 |= (0xFFFF & 0x907)
davinci_spi_bufs_pio: buf_val 0x80fe0000
davinci_spi_bufs_pio: SPIFMT0 val 0x3010
davinci_spi_bufs_pio: SPIFMT1 val 0x3010
davinci_spi_bufs_pio: SPIFMT2 val 0x3010
davinci_spi_bufs_pio: SPIFMT3 val 0x3010
davinci_spi_bufs_pio: buf_val 0x80fe0000 & SPI_SPIBUF_TXFULL_MASK 0x20000000 = 0x0
davinci_spi_bufs_pio: SPIFLG 0x1000200, count 0
#######################
davinci_spi_bufs_pio: int_status 0x1000200
starting davinci_spi_check_error
davinci_spi_check_error: ret 0
davinci_spi_bufs_pio: davinci_spi->count 2, t->len 2
davinci_spi_setup_transfer: bits_per_word 8, hz 2500000
davinci_spi_setup_transfer: bits_per_word 8
davinci_spi_chipselect: value 0
transfer: ret = 4

00 00

Видно, что в драйвер попадают все данные которые я ему отправляю. Обработка всех данных происходит за одну транзакцию, chip-select не меняет своего состояния. Под первый данные выделено 10 clock-в, что подтверждается значением SPIFMT, последнее значение A, под вторые данные выделено 16 clock-в, последнее значение 10 в SPIFMT. Таким образом суммарная посылка составляет 26 бит, 9 бит адрес + 1 бит команда + 16 бит данные.
К сожалению на осцилограффе удаётся отловить только вторую посылку и данные там корректны.
Но увы, запись значения в регистр не происходит. В чём ошибка?
Спасибо.
sasamy
Цитата(/dev/null @ Mar 17 2011, 17:23) *
DM365: сдвиговый регистр 16 бит
VITA1300: адрес 9 бит, данные 16 бит

.bits_per_word = 26,


Странно что вообще что-то работает sm.gif собственно видно что драйвер наплевал на этот параметр
Цитата
davinci_spi_setup_transfer: bits_per_word 8, hz 2500000

и передает по 8 бит на слово.
Потом учитывайте тот факт что если передавать 9 или более бит, как тут
Цитата
davinci_spi_setup_transfer: bits_per_word 10
...
davinci_spi_setup_transfer: bits_per_word 16


в слове данные читаются в соответствии с текущим endianes - у вас скорей всего LE а по SPI всегда передается MSB first.
Еще передавать и принимать вы собираетесь словами больше 8 бит а буферы у вас выровнены по границе байта
Цитата
uint8_t trv[] = {1, 8};
uint8_t twv[] = {7, 9};
struct spi_ioc_transfer wr[2] = {
[0] = {
.tx_buf = (unsigned long)trv,
.rx_buf = (unsigned long)NULL,//rx,
.len = ARRAY_SIZE(trv),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = 10
},


/dev/null
Вы не совсем правы:
- при чтении генерируются 26 clock, что подтверждается осцилографом и значением регистра SPIFMT
- что касается смутивших Вас нескольких вызовов davinci_spi_setup_transfer, то видно, что передача начинается только после настройки корректного значения
А вот за последнее замечание спасибо, но не затруднит ли Вас чуть более его расшифровать, к какому виду я должен привести свои данные для корректной записи?
Спасибо.
sasamy
Цитата(/dev/null @ Mar 18 2011, 09:18) *
Вы не совсем правы:
- при чтении генерируются 26 clock, что подтверждается осцилографом и значением регистра SPIFMT


Я уже объяснял одному товарищу куда следует засунуть осциллограф - ну не может ваш 16 битный сдвиговый регистр передать 26 бит за один раз, еще раз повоторяю - драйвер увидел несоотвествие и разбил исходный буфер на транзакции по 8 бит. Вы не понимаете что передать два раза по 8 бит или тот же буфер но за раз 16 бит - это абсолютно разные вещи если не принять мер ? Привожу пример, процессор работает в режиме little-endian, буфер 2 байта например как у вас
uint8_t trv[] = {1, 8};
в памяти будут они лежать так:
b00000001 b00001000
Если передать по 8 бит на слово то будет передано так как они лежат в памяти
0000000100001000
Если передать это как одно 16 битное слово, то слово будет передано в соответствии с spi - msb first
0000100000000001

/dev/null
Я понимаю, что 16 битный регистр не может принять за раз 26 бит, поэтому и разбиваю при записи посылку на две.
Основная идея понятна - надо посылать данные в виде 16 битного числа, буду пробовать.
bigal
"VITA1300: адрес 9 бит, данные 16 бит"
Как правило формат записи и чтения одинаковый.

".bits_per_word = 10"
При записи также должна быть одна посылка 26 бит, разбивая посылку вы теряете адрес он перезаписывается следующим пакетом.
Желательно выровнять посылку последние биты в конце передачи, тоесть первые сдвинутся и потеряются [xxx26n..16n] [15n..0n]
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.