Страниц: [1] 2 3
  Печать  
Автор Тема: Проблемы с in32 () или out32()  (Прочитано 14178 раз)
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« : Ноября 29, 2013, 12:47:58 pm »

Код:
static void Pci080ClearBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr); // читаю предыдущее значение
printf("clear bit t=%x mask=%x val=%x\n",t,bitmask,t & ~bitmask);
    out32(addr,(uint32_t)(t & ~bitmask)); // выставляю текущее
}
void Pci080PllSetup(uint32_t value, uint32_t pll_addr, Pci080DevT *dev) {
out32(pll_addr, value);
Pci080SetBit(1 << 29, dev->control); // Пытаюсь выставить 29 бит в 1
uint32_t ctrl = in32 (dev->control); // читаю результат
printf("Pci080PllSetup control = %x\n",ctrl);
}

29 (да и любой до 8 ) биты не записываются(или не читаются). Т.е если я ставлю
Код:
Pci080SetBit(1 << 7, dev->control);

то всё нормально 7 бит выставляется.

В чём может быть беда?

Возможно это связано с тем что я юзаю mmap_device_memory?
Код:
dev->base = (uint32_t) mmap_device_memory(0, info.BaseAddressSize[0],
PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, info.CpuBaseAddress[0]);

dev->control = dev->base + 0x4;
« Последнее редактирование: Ноября 29, 2013, 12:54:18 pm от denmor86 » Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #1 : Ноября 29, 2013, 01:48:29 pm »

Код:
#define pci080_in8(addr)   *(volatile uint8_t *)(addr);
#define pci080_in16(addr)  *(volatile uint16_t *)(addr);
#define pci080_in32(addr)  *(volatile uint32_t *)(addr);

#define pci080_out8(addr,val)  { *(volatile uint8_t*)(addr) = val; }
#define pci080_out16(addr,val) { *(volatile uint16_t *)(addr) = val; }
#define pci080_out32(addr,val) { *(volatile uint32_t *)(addr) = val; }
переписал функции на работу с указателем...

эффект тот же
Записан
PoP
Sr. Member
****
Offline Offline

Сообщений: 351


Просмотр профиля
« Ответ #2 : Ноября 30, 2013, 03:52:03 pm »

Может плата пдоддерживает только побайтный доступ?
Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #3 : Ноября 30, 2013, 10:05:25 pm »

судя по коду этого же драйвера под Linux:

Код:
static void mmio32_clear_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t & ~bitmask, reg);
}

должны работать запись и чтение по 4 байта...
« Последнее редактирование: Ноября 30, 2013, 10:07:57 pm от denmor86 » Записан
PoP
Sr. Member
****
Offline Offline

Сообщений: 351


Просмотр профиля
« Ответ #4 : Ноября 30, 2013, 11:24:28 pm »

Ну а readl и writel нигде не переопределены?
В описании платы указаны биты с номерами больше 7?
Получается хотябы прочитать из платы что-нибудь зарание точно известное целым двойным словом?
« Последнее редактирование: Ноября 30, 2013, 11:29:31 pm от PoP » Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #5 : Ноября 30, 2013, 11:42:25 pm »

1. Не переопределены, стандартные линуксовые используются.
2. Да описание бьётся на на блоки по 4 байта (32).
3. В первых 4 байтах находится номер версии, он статичный, и его получается корректно прочитать (прочитанный совпадает с тем что указан в описании). Далее 4 байта, всяких настроек, вот тут и Опа с записью чего либо после 7 бита, а мне бы надо их юзать.
Записан
PoP
Sr. Member
****
Offline Offline

Сообщений: 351


Просмотр профиля
« Ответ #6 : Декабря 01, 2013, 01:14:29 am »

Хотелось бы прочитать что-нибудь с не нулевым смещением Smiley. Дефолтовые настрйки платы читаются правильно? Если нет - то, видимо просто попадаете нетуда.
Если читаются правильно, попробуйте писать побайтно(пословно), но обязательно проверяйте результат 32-х байтным чтением (если уж в описании всё по 32 бита), может ложиться очень по разному, далеко не все платы поддерживают все виды адресации.
Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #7 : Декабря 01, 2013, 10:00:58 am »

К сожалению, плату от меня на 1 неделю забрали, и попробовать почитать из неё у меня получится только через понедельник.

Вот код как мапится память этой платы под Linux

Код:
p = ioremap_nocache(pci_resource_start(pdev, 0),
    pci_resource_len(pdev, 0));
if (!p)
BAIL_OUT_VERBOSELY(err_exit, -EIO,
                   "can't remap %ldK from 0x%lx\n",
                   (unsigned long)pci_resource_len(pdev, 0) >> 10,
                   (unsigned long)pci_resource_start(pdev, 0));
dev->mapped_bar0 = p;
        dev->cregs = (struct mm080_cregs *)p;

Далее все смещение идут через структуру mm080_cregs
Код:
struct mm080_cregs {
u32 ident; // Идентификационный номер ячейки(0x37550047)(ro).
u32 control; // Регистр управления(rw) имеет следующие битов.
// поля:
// 0 - разрешение прерывания по событию превышения
// установленного порога(готовность данных)
// '0' - запрещены, '1' - разрешены.
// 1 - резерв.
// 2 - ZBT_MODE_SELECT управление мультиплексором
// обращения к ZBT памяти.
// '0' - работа прошивки, '1' - загрузка/чтение.
// 3 - резерв.
// 4 - разрешение эмуляции данных с АЦП1 в память
// синус 1МГц.
// 5 - разрешение эмуляции данных с АЦП2 в память
// синус 1МГц.
// 6 - разрешение эмуляции данных с АЦП3 в память
// синус 1МГц.
// 7 - разрешение эмуляции данных с АЦП4 в память
// синус 1МГц.
// 8 - разрешение работы компоратора и рег-ции данных
// в память по всем каналам.
// 9..28 - резерв.
// 29 - запуск загрузки конф-ции PLL. Для запуска
// надо установить в '1' .
// 30 - подтверждение прерывания по событию превы-
// шения установленного порога(готовность
// данных). Для подтверждения надо записать '1'.
// 31 - программный сброс прошивки.
// Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 . В прошивке автоматический сброс
// сделан для резервных разрядов(24..28) на будущее.

u32 status; // Регистр состояния(ro) имеет след. битовые поля:
// 0 - проверка наличие качества частоты PLL1.
// 1 - проверка наличие качества частоты PLL2.
// Для битов '0' и '1' состояние "1" частота
// в норме, "0" - не в норме.
// 2..3 - резерв
// 4 - флаг превышения порога в канале 1.
// 5 - флаг превышения порога в канале 2.
// 6 - флаг превышения порога в канале 3.
// 7 - флаг превышения порога в канале 4.
// Для битов '4..7' состояние "1" - событие
// превышения, "0" - нет превышения.
// 8..29 - резерв.
// 30 - флаг прерывания по событию готовности данных
// '0' - нет события, '1' - есть событие.
// 31 - состояние линии прерывания на шине PCI
// '0' - линия в прерывании, '1' - нет прерывания.
// Прерывание снимается, когда все прерывания
// подтверждены.

u32 version; // Версия прошивки(ro).
u32 serial_num; // Серийный номер ячейки(rw), прописывается программно.
u16 threshold[4]; // Значения порога по каналам(rw).
// Разряды 0..11 - значение порога.
// Разряды 12..15 - резерв.

u32 pll_1_ctrl, pll_2_ctrl; // Регистр управления для PLL60 и PLL250(rw):
// разряды 0..6 - число M
// разряды 7,8 - число N
// разряды 9..11 - число T
};

например так
Код:
static void mmio32_set_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t | bitmask, reg);
}
static void mmio32_clear_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t & ~bitmask, reg);
}

static inline void flush_pci_txns(struct mm080_sysdev *dev)
{
readl(&dev->cregs->ident);
}
void interrupt_enable(struct mm080_sysdev *dev)
{
mmio32_set_bit(1 << 0, &dev->cregs->control);
flush_pci_txns(dev);
}
void hw_compare_enable(struct mm080_sysdev *dev)
{
mmio32_set_bit(1 << 8, &dev->cregs->control);
flush_pci_txns(dev);
}

а вот мои функции
Код:
static void Pci080SetBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr);
printf("set bit t=%x mask=%x val=%x\n",t,bitmask,t | bitmask);
out32(addr,(uint32_t)(t | bitmask));
}
static void Pci080ClearBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr);
printf("clear bit t=%x mask=%x val=%x\n",t,bitmask,t & ~bitmask);
    out32(addr,(uint32_t)(t & ~bitmask));
}
void Pci080InterruptEnable(Pci080DevT *dev) {
Pci080SetBit(1 << 0, dev->control);
pci080_in32(dev->base);
uint32_t ctrl = pci080_in32 (dev->control);
printf("Pci080InterruptEnable control = %x\n",ctrl);
}
Вообщем не пойму что я делаю не так((
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #8 : Декабря 02, 2013, 10:02:51 am »

Еще когда плата будет наберите в консоли 'pci -vvv' и все касаемое вашей платы скопипасте сюда.
Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #9 : Декабря 02, 2013, 10:54:32 am »

К сожалению доступ к плате будет только в следующий вторник.
Но я много раз смотрел вывод этой команды, какое поле вам интересно там?
Записан
vshemm
Sr. Member
****
Offline Offline

Сообщений: 317


Просмотр профиля
« Ответ #10 : Декабря 02, 2013, 06:32:22 pm »

Код:
// 9..28 - резерв.
// Разряды 24..31 сбрасываются автоматически.

Наверное, там и должны читаться нули, не?
Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #11 : Декабря 02, 2013, 07:47:52 pm »

Код:
Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 .
написано что 29 используется...
Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #12 : Декабря 02, 2013, 07:51:46 pm »

Ну я все же надеюсь, что ожидаемого действа не происходит. Странно читать назад самосбрасывающиеся биты. Хотя похоже автор это и делает, но думается это вторично, ведь надо чтото делать если оно не работает.  

По поводу вывода pci -vvv интересует все, включая хексдамп конгифспейса.

Мне все же не понятно, устройство имеет доступ через порты ввода-ввывода или через память. Может иметь и оба режима одновременно, но адреса доступа обычно будут разные. В ваших функциях вверху жуткий микс. Set/clear используют порты, enable interrupts использует set (порт) и плюс самостоятельно лезет по памяти (указатель).

Младшие биты базового регистра адреса говорят о том это ввод-вывод или память (см соответствующие макросы в pci.h), соответсвенно надо сделать mmap_device_memory() или mmap_device_io() и использовать полученный адрес для выбранного метода доступа. И лучше не чередовать/смешивать методы доступа одного и того же железа.

Записан
ed1k
QOR.Moderator
*****
Offline Offline

Сообщений: 739


Просмотр профиля WWW
« Ответ #13 : Декабря 02, 2013, 07:58:59 pm »

Код:
Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 .
написано что 29 используется...
Это шутка? Вам же по-русски написали что бит 29 используется и запускает загрузку конфигурации ФАПЧ при записи туда 1. Потом этот бит самостоятельно сбрасывается. (и читается как 0).  Иначе для повторного запуска вам приходилось бы руками его сбрасывать в ноль, потом через задержку устанавливать в один.
Записан
denmor86
Участник
*
Offline Offline

Сообщений: 35


Просмотр профиля
« Ответ #14 : Декабря 02, 2013, 08:12:53 pm »

Начну по порядку.
1. Устройство однозначно имеет доступ типа память (MEMORY) это было видно через pci -vvv. Соответственно мои потуги работать через порт IO ошибочно, и сделаны от безысходности.
2. Микс работы с IO/MEMORY так же из за того что игрался с разными функциями в надежде на положительный результат.
3. На счёт 29 бита возможно вы правы, но я пробовал и другие биты начиная с 8, наблюдал одинаковую картину. Бит не устанавливался.

А вообще извините меня за мой тупизм, первая моя работа с платой и вообще с драйверами.
Записан
Страниц: [1] 2 3
  Печать  
 
Перейти в: