1. Си / Говнокод #25156

    0

    1. 1
    2. 2
    3. 3
    4. 4
    UCSR0A |= TXC0_MASK;
    UDR0 = value;
    while ((UCSR0A & TXC0_MASK) == 0)
      ;

    The TXCn flag ... can be cleared by writing a one to its location.
    Cleared by writing one, Carl.

    Запостил: Steve_Brown, 05 Декабря 2018

    Комментарии (152) RSS

    • показать все, что скрытоvanished
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • Суслик ни разу не выполнится? И почему он с пустым телом?
      Ответить
      • Чтобы суслику не понравилось, нужно данные поxerить:
        UCSR0A ^= TXC0_MASK;
        Ответить
        • Урсалу Техас Маск, я правельно расшифровал послание?
          Ответить
          • USART0 (Universal Synchronous-Asynchronous Receiver-Transmitter №0) Control and Status Register A, TX(transmit) Complete
            0 - номер трансивера, А - ид. регистра (еще есть B, C...)
            Ответить
      • До меня сразу не дошло, что это не простые переменные, а уольшебные. Почитал тред и кажется начал что-то понимать. Проверим:
        UCSR0A |= TXC0_MASK
        Тута мы сбрасываем все взведённыйэ в регистре биты? Я правильно понял?
        while ((UCSR0A & TXC0_MASK) == 0)
        Здеся ждём пока нужные биты сбросятся? А "0)" это смайлик цыклопа?
        ;
        Пустой апиратор, поставлен на отдельной строччке для улучшения читаемости, чтобы сразу было видно что тело суслика пустое. Если я правильно помню, это было ещё в K&R. Я предпочитаю засовывать тело суслика в вагину {}, можно ещё так {;}.
        Ответить
    • > Cleared by writing one
      Нормальная практика для железок. Позволяет не проёбывать события т.к. при очистке записью нуля возможна гонка.
      Ответить
      • Ого, я проспал целый месяц! Новый год пропустил :(
        Ответить
      • Это как?
        Ответить
        • показать все, что скрытоvanished
          Ответить
          • > как тогда установить этот флаг
            Никак. Он взводится только со стороны железа и сбрасывается только со стороны софта.
            Ответить
        • Стирание нулём аля reg &= ~mask это 2 отдельных транзакции на шине. Можешь случайно скинуть лишний бит, который взвёлся между этими транзакциями. А стирание записью единички - атомарная операция.
          Ответить
          • В паинте?
            Ответить
          • Почему две? Это в случае, если маска не константа и отрицание вычисляется во время исполнения, а не при копуляции?
            Ответить
            • Предполагаю, что так память (вернее, шина) работает. По-видимому, операция OR выполняется просто поданием единичек, а AND так не реализована, нужно считать, вычислить и записать результат.
              Ответить
              • Простые шины работают тупо - можно сделать read (проц выставляет адрес, дёргает линию rd, железка выставляет ответ), можно сделать write (проц выставляет адрес и значение, дергает линию wr, железка что-то делает).

                reg &= ~mask это read, and, write

                reg = mask при стирании единичками это просто write.
                Ответить
          • То есть, если я пишу ноль в какой-нибудь бит, я могу пропустить какое-то событие от другого бита в этом же регистре? Как страшно жить.
            Разве что, наверное, это предусмотрено, и флаги с такой функциональностью не должны встречаться в одном регистре...
            Ответить
            • > могу пропустить
              Ну да.

              Можно по биту на регистр (но не особо удобно проверять если их много).
              Можно level trigger в духе "буфер пуст", который для софта r/o.
              Можно сбрасывать записью единичек.
              Можно сбрасывать сразу при чтении.

              Но сброс единичками - самый удобный способ, на самом деле. Прочитал регистр, обработал интересные тебе события, выбил их единичками. Остальные можно оставить на потом.
              Ответить
            • З.Ы. Ну и вообще лучше не думать о регистрах железок как об обычных переменных. Чтение может вызвать сайд-эффекты. При записи могут происходить странные вещи. Чтение и запись в один регистр могут вообще не иметь ничего общего, например регистры статуса (r/o) и команды (w/o) могут висеть на одном адресе...
              Ответить
            • Ну, тут, правда для установки отдельных битов есть инструкции CBI и SBI. Они работают только с регистрами, так что наверняка там как-то по-особенному реализованы, без read-OP-write. Не знаю, как в этой ардуине включить вывод листинга, но наверняка компилятор заменит |= и &=~ на соответствующую команду.
              Ответить
              • Вменяемого описания SBI/CBI я в даташите не нашёл, но есть куча вот таких замечаний:
                Due to this behavior of the receive buffer, do not use read modify write instructions (SBI and CBI) on this location.
                Do not use read-modify-write instructions (SBI and CBI) to set or clear the MPCM bit.

                Т.е. никакой магии там нет.
                Ответить
          • > Стирание нулём аля reg &= ~mask это 2 отдельных транзакции на шине. Можешь случайно скинуть лишний бит, который взвёлся между этими транзакциями. А стирание записью единички - атомарная операция.

            Ну что ты такое несешь? Не, ну если у тебя ассемблер такой кривой, то такая проблема может быть.
            Если у тебя есть машинная инструкция, которая может за раз занулить вот тот бит в том 8-битном байте без его предварительного чтения, то проблемы никакой нет. Побитовым "И" можно. Например, есть у нас регистр в котором битики
            0b10110101
            и если побитовый "И" сделать
            0b11011111
            то как раз таки вот этот битик
                V
            0b10110101
                ^
            будет занулен

            Никакого предварительного чтения тут не надо
            https://ru.wikipedia.org/wiki/Битовые_операции#Побитовое_«И»_(AND)
            > Другими словами, если оба соответствующих бита операндов равны 1, результирующий двоичный разряд равен 1; если же хотя бы один бит из пары равен 0, результирующий двоичный разряд равен 0.

            А если у процессора нет инструкции, чтобы атомарно пихнуть единичку вот в тот бит в том 8-битном байте, то и стирание через единицу тут может обосраться. Так что тогда надо будет еще всякие прерывания запрещать перед изменением битиков.
            Ответить
            • Короче:
              "Зануление" одного бита делается побитовым "И" с маской, где везде единички кроме одного места, которое зануляем.
              "Заединичивание" одного бита делается побитовым "ИЛИ" с маской, где всего одна единичка в том месте, которое нам нужно "заединичить". С чего вдруг побитовое "И" требует 2 отдельных транзакции на шине, а побитовое "ИЛИ" не требует
              Ответить
              • Ну ты бы хоть тред почитал перед тем как это писать...

                "ИЛИ" там нахуй не нужен (ОП юзает его из-за того что control и status смешали в кучу и ему не хочется вспоминать что у него было в control части). Для clear-by-writing-one нужна только запись (reg = mask). А дальше железка внутри себя уже сделает and. Т.е. мы не меняем содержимое регистра, мы отправляем железке команду на сброс нужных битов.

                > машинная инструкция, которая может за раз занулить вот тот бит
                > прерывания запрещать
                Как тебе это поможет против включения бита со стороны железки. В теории, конечно, можно было бы её научить не менять свои регистры пока ты держишь lock на шине... Но это на порядок сложнее тупого clear-by-writing-one.
                Ответить
                • > В теории, конечно, можно было бы её научить не менять свои регистры пока ты держишь lock на шине...

                  В теории можно было б просто писать/читать зарезервированные порты и не ебать мозги с этим memory-mapped peripherals

                  Вот эта хуита
                  https://developer.arm.com/products/software-development-tools/ds-5-development-studio/resources/tutorials/accessing-memory-mapped-peripherals
                  Ответить
                  • > зарезервированные порты
                    Ну да, отдельные порты психологически легче воспринимаются.

                    Но как они помогут с синхронизацией доставки ивентов от железки в твой код?
                    Ответить
                    • А чем именно чтение "памяти" по такому-то адресу (на самом деле памяти там нет) в цикле (через указатель на volatile) до тех пор пока там что-то не будет - лучше, чем чтение из порта в цикле пока что-то там не выдастся из порта?
                      В чем именно MMIO лучше с т.з. синхронизации?
                      Ответить
                      • Шо то хуйня шо это.

                        Так что сначала ждём твоего объяснения чем с т.з. синхронизации удобнее отдельные порты :)
                        Ответить
                        • Да ничем не лучше. Давайте еще например сделаем процессор, чтоб там вместо каких-то портов или каких-то MMIO использовалось например деление какого-то числа на 0. Типа если мы 0 на 0 поделили то мы такую-то хрень сделали, и вот регистре R1 у нас вот такое-то говно записалось, а если 1 на 0 поделили, то там вот тогда какое-то другое говно, и можно сделать:
                          while(SOMESHIT / 0 == SOMECRAP)
                          {
                          }

                          (на самом деле нет, т.к. по стандарту самой сишки это UB но мысль думаю ясна)
                          Ответить
                          • > ничем
                            Ну а нафиг ты тогда этот холивар MMIO vs I/O сюда принёс?

                            У MMIO всего один плюс - не надо отдельные инструкции городить.
                            Ответить
                            • Тогда давайте через деление на 0 делать - там тоже не надо отдельные инструкции городить, и memory map не расходуется на срань всякую
                              Ответить
                            • Да и кроме деления на 0 можно еще какие-нибудь инструкции альтернативно интерпретировать. Например какой-нибудь mov R0, R0. Тогда никаких отдельных инструкций не требуется
                              Ответить
                            • показать все, что скрытоvanished
                              Ответить
                              • > тяжелое наследие
                                Ну. По сути просто дополнительный бит на шине в поле адреса.
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • Х.з. может быть ещё одну дыру в адресном пространстве не хотелось прорубать? И без этого мало.
                                    Ответить
                                    • Давайте же гадать!Практически не требуется пространство ввода/вывода столь же обширное, как пространство памяти. Отвести один бит адреса (при некогда узких регистрах процессора) на MEM/IO# было бы расточительством. Отвести адекватную часть пространства типа FFxxh усложнило бы дешифрацию адреса в железе. По етому добавили отдельную линию а ля IORQ и инструкции, которые её дёргают.
                                      Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • Всем железкам пришлось бы так или иначе учитывать все-все-все биты адреса. А в случае изолированного ввода-вывода, железке, дабы определить, касается её IORQ или нет, достаточно проверить лишь условленное для платформы подмножество битов. То есть например, на каком-нибудь КудахПК с 16-битной адресной шиной и 128 адресами I/O конкретное устройство могло бы отзываться на [IORQ,A6:A0] = 10011000 (всего лишь 8 линий).

                                          Однако я тупанул и не учёл, что при memory-mapped I/O, некий "верховный" дешифратор (возможно, внутри самого CPU) мог бы выставлять подобие IORQ, и каждой железке тогда не пришлось бы проверять весь адрес целиком.

                                          Кстати, кажется, ZX Spectrum при вводе-выводе несколько младших битов адреса вообще использовал по одной штуке на отдельный аппаратный запрос.
                                          Ответить
                    • Например вот http://blablacode.ru/mikrokontrollery/288
                      void EXTI0_IRQHandler() {
                          if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
                              STM_EVAL_LEDToggle(LED3);   // сигнализируем о прерывании
                                while(RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET)  // ждём окончания работы генератора
                                {
                                }
                                uint32_t random32bit = 0;
                                random32bit = RNG_GetRandomNumber();  // получаем случайное число
                                lcd_set_cursor(0,0);   // устанавливаем курсор в начало
                                lcd_write_dec_xxxx(random32bit);  // выводим число
                              EXTI_ClearITPendingBit(EXTI_Line0);
                          }


                      Вот этот цикл while(RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) очевидно тупо читает в цикле фигню из MMIO и ждет когда там будет не RESET. С тем же успехом можно было б читать какой-нибудь порт в цикле пока там не выйдет требуемое значение
                      Ответить
            • > никакого предварительного чтения тут не надо
              У тебя ALU стоит прямо в оперативке и каждой железке? Ну ок, тогда действительно не надо.
              Ответить
              • > У тебя ALU стоит прямо в оперативке и каждой железке?

                Надо просто с префиксом LOCK делать http://www.club155.ru/x86cmd/LOCK
                В x86 даже есть особые инструкции BTR, BTS, так что OR и AND можно не использовать
                Ответить
                • > префиксом lock
                  Ну блин, lock же не отменяет джвух обращений на шине... Он тупо не даёт захватить шину другим bus master'ам между ними.

                  Плюс, как я писал выше, придётся ещё и саму железку учить понимать lock чтобы она не меняла свои регистры под лочкой.
                  Ответить
    • З.Ы. Это ты ещё не видел биты которые включаются записью 0x01234567 и 0x89ABCDEF в соседний регистр...
      Ответить
      • показать все, что скрытоvanished
        Ответить
      • Ну и на GPIO часто встречаются пары из set/clear регистров. Запись единичек в первый включает биты, запись единичек во второй выключает их. А нули означают "не трогай".

        З.Ы. Причём на STM'ках такая пара доступна через один регистр - 0x0001000 выключает первый бит, 0x00000001 включает его, 0x00020001 атомарно выключает второй и включает первый и т.п.
        Ответить
        • Ага. А в AT - регистр PIN, запись единиц в который вызывает переключение (toggle) соотверствующего бита в PORT.

          - А если 0x00010001 записать, что будет?
          - Что будет, что будет... на жопу упаду! (с)
          Ответить
      • Ну, это, наверное, что-нибудь типа защиты флешки или EEPROM от случайных операций?
        Ответить
    • показать все, что скрытоvanished
      Ответить
      • Всё лучше, чем эту вашу гомосятину.
        Ответить
        • Ты просто отравлен стереотипом, что для получения наслаждения мужчине требуется партнёр - женщина. На самом деле, наслаждение можно получать и с однополым партнёром, причём оно намного ярче и чище. К слову, мне когда-то тоже было отвратно от мысли об однополых ласках, до той поры, пока я не попробовал поласкать член ртом.
          Ответить
          • Многие мужчины-натурасты любят лизать пёзды своим пассиям - видел на порно, должен сказать, ужасное зрелище. И эти мудилы ещё смеют обзывать кого-то "хуесосом"... Если говорить о вопросах гигиены, то хуй его, мне кажется, ласкать ртом член мужчины намного гигиеничнее, чем лизать бабские гениталии. Судите сами:
            У мужчины, если он здоров, из члена идёт только моча и сперма. (ну ещё смазка, не суть.). У здоровой женщины из пизды регулярно идёт слизь, моча, кровь - ну как, аппетит разыгрался? Благодаря тому, что у мужчины половые органы - наружние, поддерживать их гигиену куда проще, чем женщинам.
            Ответить
    • > TXC0_MASK
      - консольное приложение про Сейлор Мун
      Ответить

    Добавить комментарий