Доброго времени суток.
Подскажите как правильно использовать DMA на этом звере(MPC8308).
Делаю так:
pMPC8308_D = (uint32_t*)mmap(0, 0x00100000, PROT_READ | PROT_WRITE , MAP_SHARED, hCPLD, CONFIG_SYS_IMMR);
DMAC = (DMAC_str *)mmap(0, 0x001000, PROT_READ MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset);
TCD_ = (tcd_ctrl *)mmap(0, 0x001000, PROT_READ | PROT_WRITE, MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset + 0x1000);
char *pp = new char[100];
memset(pp,0xFF,100);
TCD_->daddr = CONFIG_SYS_IMMR + DMAC_str_Offset;
TCD_->nbytes = 16;
TCD_->citer.citer = TCD_->biter.biter = 1;
TCD_->soff = 1;
TCD_->attr.ssize = 0;
TCD_->slast = 0;
TCD_->saddr = (uint32_t)pp;
TCD_->doff = 4;
TCD_->attr.dsize = 2;
TCD_->dlast_sga = -16;
TCD_->ccr.int_maj = 1;
TCD_->ccr.start = 1;
Но в итоге , по выполнению этого кода, массив "pp" никак не меняется. Что делаю не так??
Здравствуйте, Harvat, Вы писали:
H>Доброго времени суток.
H>Подскажите как правильно использовать DMA на этом звере(MPC8308).
H>Делаю так:
H>H> pMPC8308_D = (uint32_t*)mmap(0, 0x00100000, PROT_READ | PROT_WRITE , MAP_SHARED, hCPLD, CONFIG_SYS_IMMR);
H> DMAC = (DMAC_str *)mmap(0, 0x001000, PROT_READ MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset);
H> TCD_ = (tcd_ctrl *)mmap(0, 0x001000, PROT_READ | PROT_WRITE, MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset + 0x1000);
H> char *pp = new char[100];
H> memset(pp,0xFF,100);
TCD_->>daddr = CONFIG_SYS_IMMR + DMAC_str_Offset;
TCD_->>nbytes = 16;
TCD_->>citer.citer = TCD_->biter.biter = 1;
TCD_->>soff = 1;
TCD_->>attr.ssize = 0;
TCD_->>slast = 0;
TCD_->>saddr = (uint32_t)pp;
TCD_->>doff = 4;
TCD_->>attr.dsize = 2;
TCD_->>dlast_sga = -16;
TCD_->>ccr.int_maj = 1;
TCD_->>ccr.start = 1;
H>
H>Но в итоге , по выполнению этого кода, массив "pp" никак не меняется. Что делаю не так??
Код довольно странный, вы работаете напрямую с железом или нет,
используете MMU или нет?
Судя по mmap используется виртуальная память и даже есть какая-то ОС или ее подобие,
тогда `TCD_->>saddr = (uint32_t)pp;` это какая-та фигня, DMA контролер обычно с физическими адресами
работает, почему ему виртуальный адрес передается, плюс вы уверены что выделенный блок с помощью new
имеет правильно выравнивание? Плюс где "volatile"? Как компилятор поймет что все эти чтения и записи
в память не стоит оптимизировать иными словами переупорядочить, половину выкинуть как ненужные и т.п.?
Здравствуйте, Zhendos, Вы писали:
Z>Здравствуйте, Harvat, Вы писали:
H>>Доброго времени суток.
H>>Подскажите как правильно использовать DMA на этом звере(MPC8308).
H>>Делаю так:
H>>H>> pMPC8308_D = (uint32_t*)mmap(0, 0x00100000, PROT_READ | PROT_WRITE , MAP_SHARED, hCPLD, CONFIG_SYS_IMMR);
H>> DMAC = (DMAC_str *)mmap(0, 0x001000, PROT_READ MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset);
H>> TCD_ = (tcd_ctrl *)mmap(0, 0x001000, PROT_READ | PROT_WRITE, MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset + 0x1000);
H>> char *pp = new char[100];
H>> memset(pp,0xFF,100);
TCD_->>>daddr = CONFIG_SYS_IMMR + DMAC_str_Offset;
TCD_->>>nbytes = 16;
TCD_->>>citer.citer = TCD_->biter.biter = 1;
TCD_->>>soff = 1;
TCD_->>>attr.ssize = 0;
TCD_->>>slast = 0;
TCD_->>>saddr = (uint32_t)pp;
TCD_->>>doff = 4;
TCD_->>>attr.dsize = 2;
TCD_->>>dlast_sga = -16;
TCD_->>>ccr.int_maj = 1;
TCD_->>>ccr.start = 1;
H>>
H>>Но в итоге , по выполнению этого кода, массив "pp" никак не меняется. Что делаю не так??
Z>Код довольно странный, вы работаете напрямую с железом или нет,
Z>используете MMU или нет?
Z>Судя по mmap используется виртуальная память и даже есть какая-то ОС или ее подобие,
Z>тогда `TCD_->>saddr = (uint32_t)pp;` это какая-та фигня, DMA контролер обычно с физическими адресами
Z>работает, почему ему виртуальный адрес передается, плюс вы уверены что выделенный блок с помощью new
Z>имеет правильно выравнивание? Плюс где "volatile"? Как компилятор поймет что все эти чтения и записи
Z>в память не стоит оптимизировать иными словами переупорядочить, половину выкинуть как ненужные и т.п.?
Да, работаю напрямую с железом. Стоит там Power PC e300 с урезанным линуксом.
MMU не использую.
volatile попробовал, но ничего не изменилось.
Собственно до этого я с DMA не работал, но примеров по этому MPC8308RM найти не удалось.
По этому и спросил тут.
Может у кого пример есть....
Здравствуйте, Harvat, Вы писали:
H>Здравствуйте, Zhendos, Вы писали:
Z>>Здравствуйте, Harvat, Вы писали:
H>>>Доброго времени суток.
H>>>Подскажите как правильно использовать DMA на этом звере(MPC8308).
H>>>Делаю так:
H>>>H>>> pMPC8308_D = (uint32_t*)mmap(0, 0x00100000, PROT_READ | PROT_WRITE , MAP_SHARED, hCPLD, CONFIG_SYS_IMMR);
H>>> DMAC = (DMAC_str *)mmap(0, 0x001000, PROT_READ MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset);
H>>> TCD_ = (tcd_ctrl *)mmap(0, 0x001000, PROT_READ | PROT_WRITE, MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset + 0x1000);
H>>> char *pp = new char[100];
H>>> memset(pp,0xFF,100);
TCD_->>>>daddr = CONFIG_SYS_IMMR + DMAC_str_Offset;
TCD_->>>>nbytes = 16;
TCD_->>>>citer.citer = TCD_->biter.biter = 1;
TCD_->>>>soff = 1;
TCD_->>>>attr.ssize = 0;
TCD_->>>>slast = 0;
TCD_->>>>saddr = (uint32_t)pp;
TCD_->>>>doff = 4;
TCD_->>>>attr.dsize = 2;
TCD_->>>>dlast_sga = -16;
TCD_->>>>ccr.int_maj = 1;
TCD_->>>>ccr.start = 1;
H>>>
H>>>Но в итоге , по выполнению этого кода, массив "pp" никак не меняется. Что делаю не так??
Z>>Код довольно странный, вы работаете напрямую с железом или нет,
Z>>используете MMU или нет?
Z>>Судя по mmap используется виртуальная память и даже есть какая-то ОС или ее подобие,
Z>>тогда `TCD_->>saddr = (uint32_t)pp;` это какая-та фигня, DMA контролер обычно с физическими адресами
Z>>работает, почему ему виртуальный адрес передается, плюс вы уверены что выделенный блок с помощью new
Z>>имеет правильно выравнивание? Плюс где "volatile"? Как компилятор поймет что все эти чтения и записи
Z>>в память не стоит оптимизировать иными словами переупорядочить, половину выкинуть как ненужные и т.п.?
H>Да, работаю напрямую с железом. Стоит там Power PC e300 с урезанным линуксом.
H>MMU не использую.
H>volatile попробовал, но ничего не изменилось.
Надеюсь понятно, что volatile нужен для всего не только для "pp", но и для работы с "DMAC",
TCD и т.д., посмотрите как например драйверы Linux написаны, макросы writel/readl,
и работайте только через них.
Плюс ведь есть еще кэш процессора, он учитывается когда вы проверяете,
что ничего не изменилось? DMA обычно пишет мимо кэша, и нужно "форсировать" чтение из памяти,
вместо кэша. Опять в исходниках Linux есть примеры.
Ну еще для некоторых IP блоков нужно включить питание, с помощью записи в какой-нибудь регистр,
так как по умолчанию они выключены.
H>Собственно до этого я с DMA не работал, но примеров по этому MPC8308RM найти не удалось.
А зачем собственно по-нему искать, обычно у всего семейства похожие IP блоки с очень похожим
расположением регистров,
см. например
https://github.com/search?l=C&q=MPC8308+dma&type=Code
куча же примеров?
Здравствуйте, Zhendos, Вы писали:
Z>Здравствуйте, Harvat, Вы писали:
H>>Здравствуйте, Zhendos, Вы писали:
Z>>>Здравствуйте, Harvat, Вы писали:
H>>>>Доброго времени суток.
H>>>>Подскажите как правильно использовать DMA на этом звере(MPC8308).
H>>>>Делаю так:
H>>>>H>>>> pMPC8308_D = (uint32_t*)mmap(0, 0x00100000, PROT_READ | PROT_WRITE , MAP_SHARED, hCPLD, CONFIG_SYS_IMMR);
H>>>> DMAC = (DMAC_str *)mmap(0, 0x001000, PROT_READ MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset);
H>>>> TCD_ = (tcd_ctrl *)mmap(0, 0x001000, PROT_READ | PROT_WRITE, MAP_SHARED, hCPLD, CONFIG_SYS_IMMR + DMAC_str_Offset + 0x1000);
H>>>> char *pp = new char[100];
H>>>> memset(pp,0xFF,100);
TCD_->>>>>daddr = CONFIG_SYS_IMMR + DMAC_str_Offset;
TCD_->>>>>nbytes = 16;
TCD_->>>>>citer.citer = TCD_->biter.biter = 1;
TCD_->>>>>soff = 1;
TCD_->>>>>attr.ssize = 0;
TCD_->>>>>slast = 0;
TCD_->>>>>saddr = (uint32_t)pp;
TCD_->>>>>doff = 4;
TCD_->>>>>attr.dsize = 2;
TCD_->>>>>dlast_sga = -16;
TCD_->>>>>ccr.int_maj = 1;
TCD_->>>>>ccr.start = 1;
H>>>>
H>>>>Но в итоге , по выполнению этого кода, массив "pp" никак не меняется. Что делаю не так??
Z>>>Код довольно странный, вы работаете напрямую с железом или нет,
Z>>>используете MMU или нет?
Z>>>Судя по mmap используется виртуальная память и даже есть какая-то ОС или ее подобие,
Z>>>тогда `TCD_->>saddr = (uint32_t)pp;` это какая-та фигня, DMA контролер обычно с физическими адресами
Z>>>работает, почему ему виртуальный адрес передается, плюс вы уверены что выделенный блок с помощью new
Z>>>имеет правильно выравнивание? Плюс где "volatile"? Как компилятор поймет что все эти чтения и записи
Z>>>в память не стоит оптимизировать иными словами переупорядочить, половину выкинуть как ненужные и т.п.?
H>>Да, работаю напрямую с железом. Стоит там Power PC e300 с урезанным линуксом.
H>>MMU не использую.
H>>volatile попробовал, но ничего не изменилось.
Z>Надеюсь понятно, что volatile нужен для всего не только для "pp", но и для работы с "DMAC",
Z>TCD и т.д., посмотрите как например драйверы Linux написаны, макросы writel/readl,
Z>и работайте только через них.
Z>Плюс ведь есть еще кэш процессора, он учитывается когда вы проверяете,
Z>что ничего не изменилось? DMA обычно пишет мимо кэша, и нужно "форсировать" чтение из памяти,
Z>вместо кэша. Опять в исходниках Linux есть примеры.
Z>Ну еще для некоторых IP блоков нужно включить питание, с помощью записи в какой-нибудь регистр,
Z>так как по умолчанию они выключены.
H>>Собственно до этого я с DMA не работал, но примеров по этому MPC8308RM найти не удалось.
Z>А зачем собственно по-нему искать, обычно у всего семейства похожие IP блоки с очень похожим
Z>расположением регистров,
Z>см. например
Z>https://github.com/search?l=C&q=MPC8308+dma&type=Code
Z>куча же примеров?
Да
static volatile DMAC_str *DMAC;
static volatile tcd_ctrl *TCD_;
Спасибо, буду там искать