-
Постов
157 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные athlon64
-
-
Ошибочка вышла - если выводим только текст, не виснет.
Так виснет:
printf("-- TEST --\n\r");
а так - нет, но в порт ничего не выводится:
printf("-- TEST --");
В размер стэка смотреть. Перво-наперво попробовать увеличить.Если можно, для чайников - где он изменяется?
-
Процессор SAM7X512, IAR 5.4.
В проекте используются порты COM0, COM1, PIT, TWI. Основой для проекта был пример из IAR "basic-usart-hw-handshaking-project". Приём в порты COM0, COM1 сделан через регистры побайтно, вывод - через DMA. Нужно для вывода отладочного лога в DBGU форматированный вывод.
При инициализации DBGU:
PIO_Configure (DBGU_pins, PIO_LISTSIZE(DBGU_pins)); DBGU_Configure (DBGU_STANDARD, 115200, BOARD_MCK);
и попытке вывести любую строку при помощи
printf("TEST");
процессор зависает.
То же самое при выводе с помощью
TRACE_INFO("TEST");
и соответствующей инициализацией из trace.c порта DBGU.
При этом в порт ничего не попадает.
А вот
DBGU_PutChar(byte);
работает прекрасно.
Куда смотреть?
-
В общем разобрался с записью в RTC. Была ошибка в обработчике прерывания, из-за чего последний байт слался мусором.
Убрал всё лишнее, оставил только запись и чтение 1 байта в одном и том же регистре DS1340, снял осциллограммы и всё стало понятно.
Интервалов между байтами при обмене с RTC так и нет, на старой версии платы на меге256 они были и при обмене с другими модулями (слейвами) на мегах интервалы есть. Ну пока в общем всё работает.
Теперь сажусь разбираться с I2C EEPROM
-
А если попробывать писать не c 0x08 , а с 0x00 т.е сначала секунды. Записать 0x36 0x58 0x10 0x29 0x29 0x06 0x30 И не запуская счёт - прочитать.
Записал с 0 адреса последовательность: 0x36 0x58 0x10 0x02 0x29 0x06 0x30
Сразу читаю с 0 адреса: 0x02 0xFF 0xFF 0x00 0x00 0x14 0x10
И извините я это не понял. Так Вы задаёте Slaveadr?У меня просто адреса i2c устройств везде в программе 8-битные. Смещением на 1 вправо я убираю лишний бит, после чего пишу его в TWI_MMR
И почему у Вас день недели 29-ый их всего 7 и год какойто странный? И Вы про него не забываете (день недели), когда декодируете часы я его здесь не вижуВ программе день недели не используется, я в него писал дату, т.к. он всё равно урежется. Выше я вместо дня недели писал 0x02, это ничего не изменило, к сожалению :)
-
Было , такое правдо не с ARM. Теперь , перед тем как , что -то писать в DS устанавливаю его на нулевой регистр, а эатем пишу. Если регистры прочитать не все , то следущее чтение начнётся с регистра не прочитанного в предыдущем чтении.
И данные Вы записываете в BCD?
Данные записываю, конечно, закодированные в BCD.
Всегда пишу и читаю по предварительно переданному адресу регистра. Пробовал писать отдельные регистры и все 10 регистров пачкой.
Оставлял часы тикать на ночь, читая с RTC 3 раза в секунду время-дату и передавая в ком-порт. На утро часы верно насчитали прошедшие 15 часов, дата осталась корректной. Т.е. с чтением проблем нет.
Снял сегодня осциллограмму записи в RTC пачки 10 регистров начиная с адреса 0x08.
Посылка (на дату-время 10:58:36 29.06.30):
соответствует осциллограмме, единственное межбайтовых интервалов нет, всё засылается сплошняком. Читается мусор типа 00:14:10 45.00.00.0x08(адрес) 0xA9 0x00 0x36 0x58 0x10 0x29 0x29 0x06 0x30 0x00Код начала записи:
StateTWI = WriteData; // Будем писать в модуль EndDataOutTWI=11; DataOutTWI[0]=0x08; DataOutTWI[1]=0xa9; DataOutTWI[2]=0; DataOutTWI[3]=0x36; DataOutTWI[4]=0x58; DataOutTWI[5]=0x10; DataOutTWI[6]=0x29; DataOutTWI[7]=0x29; DataOutTWI[8]=0x06; DataOutTWI[9]=0x30; DataOutTWI[10]=0; PtrDataOutTWI=1; // Т.к. 0й байт уже передан, продолжаем с 1 AT91C_BASE_TWI->TWI_MMR = (CntAddrTWI >> 1) << 16; // Задаём адрес для записи в модуль AT91C_BASE_TWI->TWI_IADR = 0; // Начальный адрес регистра 0x08 AT91C_BASE_TWI->TWI_THR = DataOutTWI[0]; // Передаём на запись первый байт буфера AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START; // START AT91C_BASE_TWI->TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK; // Ловить будем успешные отправки байт и неподтверждённые приёмником посылки
Код в обработчике прерывания:
unsigned int status = AT91C_BASE_TWI->TWI_SR; // Читаем статус TWI if (status & AT91C_TWI_TXRDY) // Прошлый байт был принят приёмником (получен ACK) { if (PtrDataOutTWI >= (EndDataOutTWI)) // Если последний байт { AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP; // STOP AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF; // Выключаем все прерывания от TWI StateTWI=255; // Ставим признак свободного TWI } else AT91C_BASE_TWI->TWI_THR = DataOutTWI[PtrDataOutTWI++]; // Передаём очередной байт данных } if (status & AT91C_TWI_NACK) // Прошлый байт не был успешно принят приёмником (получен NACK) { LedErrorOn(); // Мигнём индикатором "Ошибка" AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP; // STOP AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF; // Выключаем все прерывания от TWI StateTWI=255; // Ставим признак свободного TWI }
В принципе запись в RTC будет выполняться не чаще чем раз в час, можно и пинодрыганием сделать.
Может у кого нибудь есть пример? Как реализовать задержки?
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
Ну, смотрите. Наше дело предупредить ;):) Обидно просто что со всеми другими модулями сделать обмен получилось, а с RTC запара
Насколько я помню, он моментально урезается в этом случае, т.е. лишних бит нет физически.Видимо нет. Взял такую же плату с SAM7X512 и DS1340, но без батарейки. После каждого сброса питания и до попытки синхронизировать время дата и время в RTC корректные 00:00:00 01.01.00. После записи в RTC - 45:85:85 45.25.2145, хотя судя по осциллограммам (если отключить весь остальной обмен и оставить только запись в RTC) запись проходит верно. Запутался в общем :(
-
Если коротко, то есть два пути:
1. Всеми правдами и неправдами заставить работать TWI (еррату, аппноты почитать, поэкспериментировать и т.п.)
2. Использовать программный I2C
Советую выбрать второй.
Боюсь программный I2C - не вариант.
Устройство должно каждые 2.5мс опрашивать очередной модуль и в фоне вести кучу рассчётов и формировать ответы в ком-порты максимально быстро :(
Пробую читать разное количество регистров, все значения те же, что и при считывании пачкой, ну кроме секунд и минут которые уже натикали.
Ощущение что глюк не с I2C связан.
Вопрос:
Если случайно записать в регистр (скажем по адресу 0x04H (день месяца) байт 0xFF), при чтении этого регистра будет читаться 0xFF до истечения суток по часам?
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
Реализую чтение и запись даты и времени, на SAM7X512 в IAR 5.4.
Сначала чтение сделал за один проход как чтение из микросхемы с внутренним адресом. Т.е. устанавливал внутренний адрес 0x08 и читал 9 байт.
Считывалась последовательность байт: 0xA9 0x80 0x13 0x19 0x00 0xFF 0xFF 0x00 0x00. Причём секунды и минуты (0x13 и 0x19) тикают и изменяются верно, часы и дату пока проверить не успел. Но с датой какая то ерунда - читается 45.00.0000.
Пробовал сделать чтение регистров как сказано в даташите на ds1340, т.е. сначала запись 1 байта адреса регистра, а затем повторный старт на чтение. Считывается та же последовательность байт. Осциллограммы обоих вариантов в приложении. Смутило на осциллограммах что нет межбайтовых интервалов, при обмене с другими модулями (на меге8, меге32) интервалы присутствуют.
В чём может быть подвох?
В основной программе:
StateTWI=ReadRTC; EndDataInTWI=9; PtrDataInTWI=0; // Будет прочитан ответ 9 байт AT91C_BASE_TWI->TWI_MMR = (1 << 8) | AT91C_TWI_MREAD | ((CntAddrTWI >> 1) << 16); // 1-байтовый внутренний адрес AT91C_BASE_TWI->TWI_IADR = 0x08; // Начальный адрес регистров RTC AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START; // START AT91C_BASE_TWI->TWI_IER = AT91C_TWI_RXRDY | AT91C_TWI_TXCOMP; // Ловить будем получение байта и окончание обмена по NACK на адрес
В обработчике прерывания от TWI:
unsigned int status = AT91C_BASE_TWI->TWI_SR; // читаем статус TWI if (status & AT91C_TWI_RXRDY) // Сначала был получен байт от модуля (до окончания обмена) // Устройство отправило в CPU байт { DataInTWI[PtrDataInTWI]=AT91C_BASE_TWI->TWI_RHR; // Прочитали очередной байт if (++PtrDataInTWI >= (EndDataInTWI-1)) // Если принят предпоследний байт AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP; // STOP. После этого будет принят последний байт по событию TWI_TXCOMP } if (status & AT91C_TWI_TXCOMP) // Пришёл последний байт от устройства { DataInTWI[PtrDataInTWI] = AT91C_BASE_TWI->TWI_RHR; AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP; // STOP AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF; // Выключаем все прерывания от TWI StateTWI=255; // Ставим признак свободного TWI //////------- Отладочный вывод в COM-порт принятого пакета -------- unsigned char i; for (i=0;i<(EndDataInTWI+1);i++) AddToRS(DataInTWI[i]); AddToRS(0x7E); //////-------------------------------------------------------------------------- PoiskTWI |= fPoiskTWIData; // Ставим флаг - Есть пакет на обработку }
-
Заработала отправка в USART и периодический 1мс таймер :) Спасибо
В последнем случае проблема была в том что я на время отсылки в ком-порт отключал прерывания от PIT, в это время PIT переполнялся но прерывание сгенерить не мог.
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
Начал отключать прерывания по одному, выяснилось что если выключить прерывание от PIT - посылка по USART проходит без проблем.
В обработчике прерывания PIT сделал мигалку светодиода и посмотрел осциллографом что происходит на ножке. Независимо от задаваемого периода PIT, в обработчик PIT попадаю раз в 5мкс.
Инициализация PIT:
PIT_Init(1000, 48); // period 1ms // Configure interrupt on PIT IRQ_DisableIT(AT91C_ID_SYS); IRQ_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, IRQ_PIT); IRQ_EnableIT(AT91C_ID_SYS); PIT_EnableIT(); // Enable the pit PIT_Enable();
Обработчик PIT:
void IRQ_PIT(){ //1 msek unsigned int status; status = PIT_GetStatus() & AT91C_PITC_PITS; if (status != 0) { Led_blink2(); }
PS: пробовал читать PIT_PIVR в обработчике прерывания, тогда ножка МК вообще перестаёт дрыгаться
-
В IDCR писать нули совершенно бесполезно, для разрешения прерываний существует регистр IECR.
Глобально запрещать прерывания гораздо удобнее установкой бита I регистра CPSR ядра.
Как менять биты регистра CPSR в IAR я так и не понял. В at91sam7x512.h этот регистр не объявлен
Дальше разбираюсь, возможно проблема не в запрещении/разрешении прерываний. Как выясню, отпишу :)
Зачем?!!И правда зачем?Ну как зачем. Как иначе исключить возможность прерывания передачи периодическим таймером или ещё чем то?
-
Портирую прошивку с AVR на ARM SAM7X512. В прошивке для AVR во время вывода в порты UART0, UART1 глобально запрещались и разрешались прерывания командами CLI и SEI.
В проекте для SAM7 добавил одноимённые функции:
unsigned char SREG; ////unsigned long int IMR; /*=============================================== Процедуры CLI и SEI заменяют соответствующие АВР-овские, выключают и включают все прерывания =============================================== */ void CLI(){ //// Отключает все прерывания AT91C_BASE_AIC->AIC_IDCR=0xFFFFFFFF; SREG=0x00; } void SEI(){ //// Включает все прерывания AT91C_BASE_AIC->AIC_IDCR=0; SREG=0x80; }
Процедура отправки очередного байта в ком-порт выглядит так:
void Out2COM(){ char i; if (AT91C_BASE_US0->US_CSR & AT91C_US_TXEMPTY){ //// регистр к передаче готов CLI(); if(OutBufCOMIdxWR==OutBufCOMIdxRD){ // буфер пуст OutBufCOMIdxWR=OutBufCOMIdxRD=0; if (AT91C_BASE_US0->US_CSR & AT91C_US_ENDTX){ //// Если передача закончена // Разрешаем прием по COM USART_ReadBuffer(AT91C_BASE_US0, &i, 1); COM_mode &= ~0x83; // нет пилотов и нет принятых пакетов и нет Tx AT91C_BASE_US0->US_IER = AT91C_US_RXBUFF; //// разрешаем прерывания приема СОМ } } else{ AT91C_BASE_US0->US_THR = OutBufCOM[OutBufCOMIdxRD++]; //// выдали в порт } COMWaitCnt=0; SEI(); } else if(COMWaitCnt++>5000){LedErrorOn(); while(1);} // по WatchDog'у должны сброситься }
В итоге МК пытаясь при инициализации отправить свой адрес в порт (адрес приходит нормально и МК не виснет, крутится в главном цикле main), в обработчик PIT он так и не попадает. Если убрать из процедуры отправки байта вызов CLI, то PIT работает, но вместо посылки (адреса устройства приходит байт 0x0D), видимо передачу прерывает PIT
-
После исправления обработчика и ответный пакет перестал отправляться.
Всё оказалось банально.
В обработчике проверял не тот бит.:) AT91C_US_RXRDY вместо AT91C_US_RXBUFF.
Приёмный буфер переполнялся и проц зависал
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
Заметил что если в обработчик таймаута добавить команду чтения из порта байта, то ничего не виснет.
читается при этом повторно последний байт посылки, а первый байт следующей посылки теряется
На оформление прерывания - очень похоже, что никто не пишет в AIC_EOICR. Обертка какая-нибудь в стартапе присутствуетда нет, стандартная инициализация оси и сразу инициализация порта
BSP_Init(); /* Initialize BSP functions */ OS_CPU_InitExceptVect(); /* Initialize the Vectors at address 0x00 */ #if (OS_TASK_STAT_EN > 0) OSStatInit(); #endif Mem_Init(); /* Initialize Memory Managment Module */ Math_Init(); /* Initialize Mathematical Module */ BSP_Ser_Init(115200); /* Initialize Serial port */ APP_TRACE_INFO(("\n\n\r")); ConfigureUsart(0);
-
Спасибо
Исправил на AT91C_BASE_US0->US_CR = AT91C_US_STTTO; :rolleyes:
Теперь ответ на каждый пакет приходит нормально и светодиод, который по таймауту должен загораться/гаснуть, отрабатывает верно.
Теперь вопрос скорее по операционке. После приёма по USART первого пакета останавливаются все остальные задачи (опрос по TWI, мигание диодом). Куда смотреть?
Обработчик теперь выглядит так:
void USART0_IrqHandler(void) { if ((AT91C_BASE_US0->US_CSR & AT91C_US_TIMEOUT) > 0) { // если прерывание произошло по таймауту BSP_LED_Toggle(1); AT91C_BASE_US0->US_CR = AT91C_US_STTTO; //Сбрасываем тайм-аут } else if ((AT91C_BASE_US0->US_CSR & AT91C_US_RXRDY) == 1) { // если прерывание произошло по заполнению буфера USART_ReadBuffer(AT91C_BASE_US0, &pBuffer, 1); USART_Write(AT91C_BASE_US0,pBuffer,0); }
-
Процессор At91SAM7X512, IDE IAR 5.4, uCOS 2.89
Тайм-аут мне нужен чтобы определять окончание пакета.
С отдельным таймером для отсчитывания тайм-аута всё работает. Интересно использовать именно заложенную в USART аппаратную функцию. Прочитал раздел даташита про USART несколько раз, но всё равно чтото гдето забыл :(
Процессор получает пакет и даже успевает его пульнуть обратно, но по истечении таймаута процессор виснет.
Инициализация USART0:
void ConfigureUsart(unsigned char usart_num) { unsigned int mode = AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT | AT91C_US_CHMODE_NORMAL; PIO_Configure(USART0_pins, PIO_LISTSIZE(USART0_pins)); // Enable the peripheral clock in the PMC PMC_EnablePeripheral(AT91C_ID_US0); PMC_EnablePeripheral(AT91C_ID_US0); // Configure the USART in the desired mode @9600 bauds USART_Configure(AT91C_BASE_US0, mode, 9600, 48000000); // Configure the USART interrupt IRQ_ConfigureIT(AT91C_ID_US0, 0, USART0_IrqHandler); IRQ_EnableIT(AT91C_ID_US0); // Enable receiver & transmitter USART_SetTransmitterEnabled(AT91C_BASE_US0, 1); USART_SetReceiverEnabled(AT91C_BASE_US0, 1); // Start receiving data and start timer USART_ReadBuffer(AT91C_BASE_US0, &pBuffer, 1); AT91C_BASE_US0->US_IER = AT91C_US_RXBUFF | AT91C_US_TIMEOUT; //------------------------------------------------------------------------------ // Устанавливаем тайм-аут AT91C_BASE_US0->US_RTOR=70u; }
Обработчик прерывания:
void USART0_IrqHandler(void) { if ((AT91C_BASE_US0->US_CSR & AT91C_US_TIMEOUT) > 0) // если прерывание произошло по таймауту BSP_LED_Toggle(1); else if ((AT91C_BASE_US0->US_CSR & AT91C_US_RXRDY) == 1) { // если прерывание произошло по заполнению буфера USART_ReadBuffer(AT91C_BASE_US0, &pBuffer, 1); USART_Write(AT91C_BASE_US0,pBuffer,0); AT91C_BASE_US0->US_CR =AT91C_BASE_US0->US_CR | AT91C_US_STTTO; //Начинаем отсчёт тайм-аута } }
-
Здравствуйте
Отладку веду на плате AT91SAM7X256, IDE - IAR.
Реализую обмен устройства с компьютером по com-порту. Взял за основу пример из IAR "basic-usart-hw-
handshaking-project". Сделал ответ на команды компьютера, используя функции printf и put_char. Всё прекрасно работает.
Теперь возникла необходимость чтобы устройство могло отвечать на команды по обоим портам USART0, USART1 +
должно отправлять отладочные сообщения в DBGU + нужно перевести проект на microC/OS-II. В связи с чем вопрос, как перенаправить функции printf и
put_char на нужный мне порт? Возможно поделитесь своими наработками или идеями?
Заранее благодарю :)
Извините если написал не в тот раздел, вопрос скорее про перенаправление printf/put_char
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
В опциях проекта измените процессор на установленный в вашей платеНе компилируется, ругается что не может прицепить intrinsic.c и на стартап :crying:
-
Опубликовано · Изменено пользователем athlon64 · Пожаловаться
Попробовал реализовать программный I2C - сигналы зашевелились, получилось передать слейву простейший пакет с его адресом. Теперь слейв перестал стоять в ошибке изза отсутствия опроса. Не получается ничего прочитать из слейва. Видимо не правильно перевожу ногу TWDA в режим входа. И остался вопрос как организовать правильные тайминги? Т.к. периодически слейв всё таки теряет "опрос", встаёт в ошибку.
-
-
Программную реализацию делать не хотелось бы, очень уж часто придётся отвлекаться на опрос по I2C, а ещё есть куча других рассчётов и обмен по другим интерфейсам.
Поиском пользуюсь, но ничего по моей проблеме не нахожу. Может быть есть у кого-нибудь рабочая реализация асинхронного обмена по I2C для такого процессора с чем то кроме атмеловского eeprom?
-
Необходимо на SAM7X256 в режиме мастера опрашивать устройство по I2C (устройство сделано на меге8, представляет собой БП с контролем напряжения, умеет выдавать его по I2C, работает в режиме слейв, обеспечивает подтяжку к +12В). В качестве буфера применил P82B96 (проверил, уровни верные).
За основу взял пример basic-twi-eeprom-project, стандартные библиотеки twi и twid. После инициализации TWI уровни TWCK и TWD +12В, как положено.
#define TWCK 100000 AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TWI;//AT91C_ID_TWI; TWI_ConfigureMaster(AT91C_BASE_TWI, TWCK, BOARD_MCK); TWID_Initialize(&twid, AT91C_BASE_TWI);
После попытки прочитать чтолибо из устройтва SAM7X256 роняет уровни TWCK и TWD до 0В и держит. Байты не передаёт. Посылка бита STOP в TWI линии не отпускает. Естесственно флаг принятого байта от устройства не выставляется. В асинхронном режиме не попадаем в прерывание по принятому байту, в синхронном циклимся ожидая байт (убрал проверку таймаута, иначе постоянный таймаут).
Пробовал циклить чтение из устройства
while(1) TWID_Read(&twid, 0x08, 0, 0, pData, 8,0);
смотрел что творится на TWI осциллографом - обе линии лежат в нуле и не шевелятся. На команду STOP реакции нет.
Сорри за сумбур, формулировал в торопях.
В чём может быть проблема?
-
В моём проекте под арм9 была возможность выбора в параметрах проекта используемого слота под флэшку, то есть какой именно SPI и CS должен быть задействован. Проверьте, может быть идёт обращение не к тому SPI.
Так и есть, исправил в main.c все задефайненные ..._SPI_A_... на ..._SPI_B_... (для флешки на этой плате используется SPI B) и пример заработал.
Спасибо за подсказку :)
-
Появилась необходимость во внешнем хранилище данных, пытаясь использовать имеющийся на отладочной плате AT45DB642 столкнулся с тем что флеш не отвечает. Откомпилирован стандартный проект IAR для этой платы basic-dataflash-project. В DBGU отсылается:
-- Basic Dataflash Project 1.7-rc1 -- -- AT91SAM7X-EK -- Compiled: Apr 12 2010 14:38:39 -- -I- Initializing the SPI and AT45 drivers -I- At45 enabled -I- SPI interrupt enabled -I- Waiting for a dataflash to be connected ...
И стоит в таком состоянии бесконечно, как будто микросхема отсутствует
Бывало пару раз выскакивали такие ошибки, через некоторое время после подачи питания на плату
-I- AT45DB2562 detected -I- Device identifier: 0xFFFFFFFF -E- Could not write page 0ge: 0 -E- Test failed.
В описании платы не нашёл никаких джамперов, необходимых для работы AT45DB642. Убирание J19 ничего не даёт.
Я так понимаю флешка труп? Может быть есть какой то ньюанс?
Зависания на printf
в ARM, 32bit
Опубликовано · Пожаловаться
Увеличил размер стека в icf-файле с 4Кб до 8Кб. Не полегчало