|
Тонкости работы с LPC2xxx, много разных мелочей |
|
|
|
Nov 15 2007, 14:53
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Nov 15 2007, 15:38)  Но появились новые сведения. Выкладывайте ваши карты. Я скачал узер мануал и внимательно прочитал раздел про порты, хотя с 213х не работаю и пока не планирую. Ничего особенного про 0.31 там нет. Более того: Цитата Bit 0 in IO1PIN corresponds to P1.0 ... Bit 31 in IO1PIN corresponds to P1.31 ....... Following code will preserve existing output on PORT0 pins P0.[31:16] and P0.[7:0] and at the same time set P0.[15:8] to 0xA5, regardless of the previous value of pins P0.[15:8]: IO0PIN = (IO0PIN && #0xFFFF00FF) || #0x0000A500 Скачал эррату. Там тоже ничего про эту ногу нет. Эррата датирована июлем - если бы особенности были, их бы с тех пор успели найти и описать. Поэтому я не понимаю, почему IO0PIN ^= (1U << 31); может не работать и почему, скажем, IO0PIN ^= (1U << 20); может испортить 31 бит. Не томите
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 15 2007, 15:20
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ) IO0PIN = (IO0PIN && #0xFFFF00FF) || #0x0000A500 Ну если они в этом выражении умудрились столько ошибок наставить, то неудивительно, что про особенность P0.31 в попыхах забыли. Ведь не только я вставал на эти грабли. Другие подтвердят. При чтении из IOPIN0 старший бит всегда читается установленным.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 15 2007, 15:34
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(GetSmart @ Nov 15 2007, 17:20)  Ведь не только я вставал на эти грабли. Другие подтвердят. При чтении из IOPIN0 старший бит всегда читается установленным. Хорошо, поверю на слово. Тогда надо читать IO0SET. IO0PIN = IO0SET ^ (1U<<31 ); или IO0SET & (1U<<31 ) ? IO0CLR = (1U<<31 ) : IO0SET = (1U<<31 ); или развивая тему (signed int)IO0SET < 0 ? IO0CLR = (1U<<31 ) : IO0SET = (1U<<31 );
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Nov 15 2007, 15:53
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Сергей Борщ) Тогда IO0PIN = ( IO0PIN & ~(1U << 31) ) | ( IO0CLR & (1U<<31 )); Орригинально  Однако неправильно. Тем более, что IO0CLR Write Only! Щас, подождём zltigo и произойдёт чудо  Цитата(Сергей Борщ) Тогда надо читать IO0SET. IO0PIN = IO0SET ^ (1U<<31); Вот именно!!! Там хранится реально выводимое значение порта, даже если какой-либо пин в данный момент сделан входом. Это значит если на лету переключить пин на вывод, то именно значение из IOxSET появится на этом выходном пине. Короче, это самый простой и правильный метод инверсии выходных пинов. Вне зависимости от того, на вход или выход и на какую альтернативную функцию в данный момент пин настроен.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 15 2007, 16:21
|

бессмертным стать можно тремя способами
    
Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912

|
Пока что умнее чем #define LED_TOGGLE() \ IO1PIN & (1<<LINK_LED_IOPIN) ? (IO1CLR = (1<<LINK_LED_IOPIN)) : (IO1SET = (1<<LINK_LED_IOPIN)); не придумал
вот код который генерится:
ldr r2, [pc, #72] ; 0x2f8 <main+152> ldr r3, [r2, #16] tst r3, #16777216 ; 0x1000000 movne r3, #16777216 ; 0x1000000 moveq r3, #16777216 ; 0x1000000 strne r3, [r2, #28] streq r3, [r2, #20]
м
|
|
|
|
|
Nov 15 2007, 17:20
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(klen) IO1PIN & (1<<LINK_LED_IOPIN) ? (IO1CLR = (1<<LINK_LED_IOPIN)) : (IO1SET = (1<<LINK_LED_IOPIN)); Скажем так, по условию задачи нельзя читать текущее состояние из IOxPIN. Для P0.31 это так на самом деле. А самый короткий способ как на Си, так и на АSMе я уже написал: IOxPIN = IOxSET ^ (1U<<n); ЗЫ: Меня всегда интересовало почему IOxSET для чтения/записи, а IOxCLR только для записи. И недавно я это выяснил  Теперь всё встало на свои места!
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 16 2007, 06:36
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(GetSmart @ Nov 15 2007, 20:20)  ЗЫ: Меня всегда интересовало почему IOxSET для чтения/записи, а IOxCLR только для записи. И недавно я это выяснил  Теперь всё встало на свои места! Да, это нюанс, который проясняет назначение IOxSET для чтения. Спасибо. Я подумаю над изменением #define Test_LED3 (IO0PIN_bit.P0_31) на #define Test_LED3 (IO0SET_bit.P0_31) Но теперь остается еще нюансы с IOxPIN. Я так понимаю. Если биты порта сконфигурированы как GPIO (я подчеркиваю это), то IOxPIN в этих битах указывает состояние на самих пинах. Т.е. если бит сконфигурирован как выход, то состояние выхода. Если бит сконфигурирован как вход, то состояние входа. Теперь объясните мне, за что сражались.  Цитата(Сергей Борщ @ Nov 16 2007, 03:34)  Да, познавательно. Спасибо! Полез редактировать свои макросы. Зачем так спешить. Цитата(alexander55 @ Nov 16 2007, 08:46)  Я подумаю над изменением #define Test_LED3 (IO0PIN_bit.P0_31) на #define Test_LED3 (IO0SET_bit.P0_31) Проверил, работают аналогично. Что лучше реальное состояние выхода или записанное - вопрос, конечно, интересный.
|
|
|
|
|
Nov 16 2007, 08:37
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(alexander55 @ Nov 16 2007, 11:36)  Но теперь остается еще нюансы с IOxPIN. Я так понимаю. Если биты порта сконфигурированы как GPIO (я подчеркиваю это), то IOxPIN в этих битах указывает состояние на самих пинах. Т.е. если бит сконфигурирован как выход, то состояние выхода. Если бит сконфигурирован как вход, то состояние входа. Теперь объясните мне, за что сражались.  Уже написал. Повторяю для особо невнимательных: В процессоре LPC213x при чтении IO0PIN старший бит читается установленным ВСЕГДА!!! Поэтому любая конструкция типа IO0PIN ^= (1<<N) разрушит содержимое этого пина, а точнее установит на нём еденицу. Для LPC214x не проверял, особенно в старых ревизиях.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Nov 26 2007, 05:57
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(GetSmart @ Nov 23 2007, 18:07)  Оказывается аналогичная ситуация с и с другими регистрами, в которых используется пара функций SET / CLR. Например VICIntEnable / VICIntEnClr и VICSoftInt / VICSoftIntClear. Из VICIntEnable и VICSoftInt можно читать всю карту разрешённых/установленных прерываний, а запись значения может только устанавливать биты, но не сбрасывать. Это очень логично с точки зрения унификации. Хотя, для портовых регистров возможность чтения по актуальности намного выше. Инверсии выходов используются для организации частотных выходов (это используется достаточно часто). PS. GetSmart, спасибо за Ваши исследования (никогда не знаешь, что может понадобиться со временем). Я за четкость понимания, особенно, если производитель что-то не договаривает.
|
|
|
|
|
Nov 27 2007, 06:07
|
Местный
  
Группа: Свой
Сообщений: 359
Регистрация: 9-12-05
Пользователь №: 12 034

|
Не знаю что вы тут с GPIO нового нашли. У меня ещё в древнем мануале на 2114/.../2214 написано: Цитата GPIO Output Set Register (IO0SET - 0xE0028004, IO1SET - 0xE0028014, IO2SET - 0xE0028024, IO3SET - 0xE0028034) This register is used to produce a HIGH level output at the port pins if they are configured as GPIO in an OUTPUT mode. Writing 1 produces a HIGH level at the corresponding port pins. Writing 0 has no effect. If any pin is configured as an input or a secondary function, writing to IOSET has no effect. Reading the IOSET register returns the value of this register, as determined by previous writes to IOSET and IOCLR (or IOPIN as noted above). This value does not reflect the effect of any outside world influence on the I/O pins. Цитата Applications that require instanatneous appearance of zeros and ones on the respected parallel port can use direct access to port’s corresponding GPIO Pin Value Register (IOPIN). Assuming that pins P0.8 to P0.15 are configured as output, write to IO0PIN: IO0PIN = 0x0000 C700 will produce the same output as following sequence of writes: IO0SET = 0x0000 C700 IO0CLR = 0x0000 3800 Solution utilizing access to IO0SET and IO0CLR will take more steps compared to a single IO0PIN write access. Хотя тамже IO0PIN и указан как RO. Другими словами: Чтение IOхPIN читает реальное состояние пинов, например для сконфигурённого на выход пина с установленным в нём нулём, из IOхPIN можно прочитать единицу если этот порт сильно нагружен, например сильноточным светодиодом. (ни в коей мере не призываю выходить за границы дозволеных токов.) Чтение IOxSET читает то что задумывалось программерами на выход. (даже если пин сконфигурён как вход). Запись в IOxPIN - есть параллельная запись всего порта.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|