Как стать автором
Обновить

Комментарии 9

Вот, вот это я понимаю — программирование AVR :)

Прочитал статью, не понял, где мьютекс то. Вы так очередь заданий назвали, да?

Jumptable через switch() { case :… default: } не получается компактнее? Кажется, вы оставили очень мало простора для компилятора. По поводу размера структур — тут можно попробовать использовать кольцевые буферы, тогда можно будет отказаться от лишних указателей. У вас, на сколько я понял, bufTx уже выполняет такую роль, в него можно и команду с адресом и количеством байт положить.

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

switch-case:
00000071  IN R24,0x01      In from I/O location 
00000072  CPI R24,0x28      Compare with immediate 
00000073  BRNE PC+0x02      Branch if not equal 
00000074  RJMP PC+0x0045      Relative jump 
00000075  BRCC PC+0x10      Branch if carry cleared 
00000076  CPI R24,0x10      Compare with immediate 
00000077  BREQ PC+0x26      Branch if equal 
00000078  BRCC PC+0x07      Branch if carry cleared 
00000079  TST R24      Test for Zero or Minus 
0000007A  BREQ PC+0x20      Branch if equal 
0000007B  CPI R24,0x08      Compare with immediate 
0000007C  BREQ PC+0x02      Branch if equal 
0000007D  RJMP PC+0x0090      Relative jump 
0000007E  RJMP PC+0x001F      Relative jump 
0000007F  CPI R24,0x18      Compare with immediate 
00000080  BREQ PC+0x39      Branch if equal 
00000081  CPI R24,0x20      Compare with immediate 
00000082  BREQ PC+0x02      Branch if equal 
00000083  RJMP PC+0x008A      Relative jump 
00000084  RJMP PC+0x0054      Relative jump 
00000085  CPI R24,0x40      Compare with immediate 
00000086  BRNE PC+0x02      Branch if not equal 
00000087  RJMP PC+0x005A      Relative jump 
00000088  BRCC PC+0x08      Branch if carry cleared 
00000089  CPI R24,0x30      Compare with immediate 
0000008A  BRNE PC+0x02      Branch if not equal 
0000008B  RJMP PC+0x0050      Relative jump 
0000008C  CPI R24,0x38      Compare with immediate 
0000008D  BREQ PC+0x02      Branch if equal 
0000008E  RJMP PC+0x007F      Relative jump 
0000008F  RJMP PC+0x004F      Relative jump 
00000090  CPI R24,0x50      Compare with immediate 
00000091  BRNE PC+0x02      Branch if not equal 
00000092  RJMP PC+0x005C      Relative jump 
00000093  CPI R24,0x58      Compare with immediate 
00000094  BRNE PC+0x02      Branch if not equal 
00000095  RJMP PC+0x0070      Relative jump 
00000096  CPI R24,0x48      Compare with immediate 
00000097  BREQ PC+0x02      Branch if equal 
00000098  RJMP PC+0x0075      Relative jump 
00000099  RJMP PC+0x0052      Relative jump

lookup table:
0000008C  IN R30,0x01      In from I/O location 
0000008D  LSR R30      Logical shift right 
0000008E  LSR R30      Logical shift right 
0000008F  LSR R30      Logical shift right 
00000090  LDI R31,0x00      Load immediate 
00000091  LSL R30      Logical Shift Left 
00000092  ROL R31      Rotate Left Through Carry 
00000093  SUBI R30,0xAC      Subtract immediate 
00000094  SBCI R31,0xFF      Subtract immediate with carry 
00000095  LPM R24,Z+      Load program memory and postincrement 
00000096  LPM R25,Z      Load program memory 
00000097  PUSH R24      Push register on stack 
00000098  PUSH R25      Push register on stack 
00000099  RET       Subroutine return

Да, BufTX является кольцевым, но не предусматривает переполнение.
Никак. Но это можно предусмотреть, содержа в структуре флаг. И только после полной обработки полученных данных его скидывать, тем самым говоря что в эту ячейку можно записать новую.
ну калибровочные коэффициенты можно считывать только один раз — это во первых, во вторых — тут вопрос разумности этого всего — ведь время измерения давления довольно велико, а без новых значений от дачтика — скорей всего вашей системе просто нечего делать — конечный автомат изменяет свое состояние в соответствии с новыми данными — то есть — получили данные, проанализировали, конечный автомат сделал шаг — ждем новых данных, время обработки данных — на порядок минимум будет меньше времени ожидания этих данных — так стоит ли тут экономить такты, если система 99% времени бездействует? А так — полезно на первый взгляд — может быть пригодится в каких то нагруженных системах
В этом случае кострункция себя не оправдывает. В рабочем варианте мне нужно одновременно запускать 2 датчика на преобразование и получить время. А для этого уже нужно послать 3 обращения подряд. Да и лепить все через _delay_ms(ххх) тоже не дело, да и еще вручную следить чтобы ххх было достаточно для передачи. А вдруг скорость передачи нужно будет снизить? Тогда и полезут всякие дебри. Но фишка не в этом. Как вы сказали в действительно загруженных системах это может помочь.
Прототреды же есть, легковесные и удобные.

Вызвали функцию получения по шине первого блока данных, выставили флажок, ушли в прототредовский слип (читай — освободили процессор для следующей задачи). Интеррапт флажок сбросил.
Получаем красивый и чистый код.
Примерно такого вида код будет, на мой взгляд, очень читабельный:

PT_THREAD(GetAllRegisters(struct pt *pt))
{
	PT_BEGIN(pt);
	PT_WAIT_UNTIL(pt,BusReady);
        GetData(Reg1);
	PT_WAIT_UNTIL(pt,BusReady);
        GetData(Reg2);
	PT_WAIT_UNTIL(pt,BusReady);
        GetData(Reg3);
	PT_END(pt);
}
Можно подробнее? Стало интересно. Не совсем въехал как эта контсрукция выбирает что пойдет следующим.
Как уже написали выше, присмотритесь к протопотокам о них уже писали тут.
Я могу предложить свою библиотеку для AVR: например, вот модуль i2c, примеры как с ним работать есть тут и тут, а вот очередь.
Мьютекс в статье я не увидел, присмотритесь к конструкции ATOMIC_BLOCK.
Хорошо) я почитаю про эти протопотоки. Никогда о них не слышал ранее. И прошерстю вашу библиотеку. Спасибо.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории