0

Записи в HW регистрирующую через/DEV/MEM нуждается в дополнительной WRITEЗаписи в HW регистров через/DEV/MEM нуждается в дополнительной записи

Я хочу написать в какое-то HW регистров с использованием/DEV/MEM на Linux. Целевая плата - ZYBO (Zynq, ARM Cortex-A9), а HW - это AXI4 Lite Slave с 4 регистрами, которые автоматически генерируются Xilinx Vivado.

Вот код C для записи в регистры HW.

#include <sys/mman.h> 
#include <fcntl.h> 
#include <stdio.h> 

#define MAP_BASE  (0x43c30000) 
#define MAP_RANGE  (0x10000) 

int main(int argc, char *argv[]) 
{ 
     volatile unsigned int *p; 
     void *iomap_ptr; 
     int fd, i, v; 

     fd = open("/dev/mem", O_RDWR | O_SYNC); 
     iomap_ptr = mmap(0, MAP_RANGE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MAP_BASE); 

     p = (volatile unsigned int *)iomap_ptr; 
     for (i = 0; i < 4; i++) 
       p[i] = i; 
     for (i = 0; i < 4; i++) 
       printf("%04X: %08X\n", i, p[i]); 

     munmap(iomap_ptr, MAP_RANGE); 
     close(fd); 
     return 0; 
} 

При запуске кода C в первый раз, результат:

0000: 00000000 
0001: 00000001 
0002: 00000002 
0003: 00000000 

Кажется, что окончательное запись не применяется.

Затем, когда я запускаю код C еще раз, результат:

0000: 00000000 
0001: 00000001 
0002: 00000002 
0003: 00000003 

После расследования, я понял, что мне нужна дополнительная запись в HW для применения последней записи.

Как я могу записать в регистры HW без дополнительной записи?

+0

Вам нужно очистить часть D-Cache? Xilinx должен иметь некоторые макросы/функции для недействительности/очистки кэша для определенных диапазонов адресов. – rjp

+0

@rjp: Это адресное пространство не является «неотделимым/не-кэшабельным/строго упорядоченным» (надеюсь, что я ничего не пропустил), аппаратный дизайн нарушен. Проблемы с кэшем не должны возникать в периферийном регистровом пространстве. – Olaf

+0

@ Олаф, я не согласен. Я не работал на стороне Vivado, поэтому я не знаю, нужно ли это указывать и/или если это то, что можно настроить неправильно. – rjp

ответ

0

Чтобы предисловие к этому, я как-то пропустил важную информацию в вопросе, поэтому содержание этого ответа гораздо менее переносимо, чем должно быть, но я считаю, что он все еще может решить проблему. Есть два взаимосвязанных вопроса на SO конкретных к Zynq и ММАП:

Flush cache to DRAM

How to get writes via an mmap mapped memory pointer to flush immediately?

Функции кэша Xilinx, перечисленные здесь, по-видимому, в конечном счете, использовать тот же метод, как лучший ответ на первый связан вопрос ,


Это, скорее всего, проблема с кешированием. В данном конкретном случае, вы можете использовать библиотеку Xilinx, чтобы очистить диапазон адресов, что ваши регистры находятся в заголовочном файле xil_cache.h имеет две функции, которые могут быть использованы для этого:.

void Xil_DCacheFlush(void); 
void Xil_DCacheFlushRange(unsigned int adr, unsigned len); 

В зависимости от версии, вы можете иметь третий вариант (с несколько различных прототипов):

void Xil_DCacheFlush(void); 
void Xil_DCacheFlushRange(INTPTR adr, u32 len); 
void Xil_DCacheFlushLine(INTPTR adr); 

Первая функция, Xil_DCacheFlush смоет весь кэш. Это не является особенно желательным поведением, так как потенциально может быть много кэшированных данных, которые не имеют отношения к проблеме, очищаемой и недействительной, поэтому вы можете увидеть влияние производительности.

Третья функция, Xil_DCacheFlushLine, если она имеется, вероятно, будет работать в этом случае, поскольку у вас есть только четыре регистра. Это заставит записи (если строка грязная), а затем приведет к недействительности кеша, поэтому следующее чтение будет пропущено и должно быть извлечено из вашего регистра. Однако это не лучшее решение, поскольку оно основывается на нескольких предположениях относительно вашего периферийного устройства.

Вторая функция, Xil_DCacheFlushRange, вероятно, является функцией, которую вы хотите. С помощью этой функции вы можете указать диапазон адресов вашего периферийного устройства. В этом случае он мал, но это решение масштабируется для сложных периферийных устройств с очень большими наборами регистров.

После того, как вы выполнили запись в регистре, вы сможете вызывать любую из вышеперечисленных функций, которые вы хотите очистить от всего или части кеша данных.

Также может быть способ отключить кеширование этого диапазона адресов в вашем дизайне, хотя мне трудно найти хорошую ссылку для этого, и у вас может не быть детализации в регионе, где вы хотите.

+1

Если/dev/mem возвращает кэшируемое отображение, что-то, вероятно, ужасно ошибочно. – Notlikethat

+0

Да, я как-то пропустил этот бит. Это похоже на то, что у других людей была такая же проблема на Zynq: http://stackoverflow.com/questions/20750176/how-to-get-writes-via-an-mmap-mapped-memory-pointer-to-flush - немедленно – rjp

+0

Чем больше я думаю об этом, тем меньше он имеет смысл. Другие вопросы действительно связаны с проблемами кэша с 'mmap' на Zynq, но в этом случае я не понимаю, почему письменное значение не вернется, даже если оно не попало в периферийные регистры, поскольку правильное значение должно быть в кеше. – rjp

 Смежные вопросы

  • Нет связанных вопросов^_^