LINUX.ORG.RU

MSP430. Вопрос к тем кто работал с PDP-11. Программирование машинными кодами. Поделитесь опытом.

 , ,


0

2

В руки попал микроконтроллер MSP430 с платой LaunchPad. Искал какие есть инструменты для программирования и прошивки. В составе MSPFlasher попался файл Firmware.txt следующего содержания:

@e000
21 83 B2 40 80 5A 20 01 F2 D3 22 00 F2 E3 21 00 
B1 40 10 27 00 00 91 83 00 00 81 93 00 00 FB 23 
F5 3F 31 40 00 04 B2 40 48 E0 00 02 B2 40 48 E0 
02 02 B0 12 40 E0 0C 43 B0 12 00 E0 B0 12 44 E0 
1C 43 30 41 03 43 FF 3F 30 41 
@fffe
22 E0 
q

С помощью другой программы mspdebug у меня получилось зашить этот Firmware.txt:

$ ./mspdebug rf2500
(mspdebug) erase
Erasing...
(mspdebug) load ../MSPFlasher_1.3.20/Firmware.txt 
Done, 76 bytes total
(mspdebug) exit

После этого светодиодики бодро заморгали на плате.

Мне захотелось тоже попробовать хоть что-нибудь написать таким образом, просто чтобы был такой опыт. Если верить википедии, у MSP430 схожая система команд с PDP-11. Я относительно молодой, PDP-11 совсем не застал.

Здесь на форуме от разных людей видел комментарии в духе «дайте мне в руки PDP-11 и я вспомню как это делается». В руки, увы, ни PDP-11, ни MSP430 не дам. Но если поделитесь опытом, буду очень рад!

Вот, что, к примеру, делает программа описанная в файле Firmware.txt? Я, например, пока не могу расшифровать. :^)

Ответ на: комментарий от Jullyfish

для этого надо сначала в машкодах разобраться

Пока делаете симулятор, разберётесь и в кодировании инструкции, и в том, как они должны работать, и во многом другом…

vM ★★★
()

Сам, конечно, не разбирался, но ИИшница выдала вот это:

E000:  SUB.W  #2, SP                ; Allocate a 2-byte local counter

E002:  MOV.W  #0x5A80, &0x0120      ; WDTCTL: disable watchdog
E008:  BIS.B  #0xFF, &0x0022        ; P1DIR: set all direction bits

; Outer loop:
E00C:  XOR.B  #0xFF, &0x0021        ; P1OUT: invert all output bits
E010:  MOV.W  #10000, 0(SP)         ; counter = 10000

; Delay loop:
E016:  DEC.W  0(SP)                 ; --counter
E01A:  TST.W  0(SP)                 ; Compare counter with zero
E01E:  JNE    0xE016                ; Repeat until zero

E020:  JMP    0xE00C                ; Toggle again, forever

Примерный код на C, которому эта программа соответствует:

#include <msp430.h>
#include <stdint.h>

int main(void)
{
    volatile uint16_t counter;

    // Disable the watchdog.
    WDTCTL = WDTPW | WDTHOLD;

    // Configure all eight Port 1 pins as outputs.
    P1DIR |= 0xFF;

    for (;;) {
        // Invert every Port 1 output bit.
        P1OUT ^= 0xFF;

        // Busy-wait delay.
        counter = 10000;
        do {
            --counter;
        } while (counter != 0);
    }
}

Судя по твоему описанию это программа, которая моргает светодиодом, работая с GPIO-пином.

vbr ★★★★★
()

Мне захотелось тоже попробовать хоть что-нибудь написать

Накодить или написать?

Систему программирования этого устройства с тумблерно-светодиодной консоли в стиле начала 1970-х?

vM ★★★
()
Ответ на: комментарий от algo

Ассемблер, т.е. программка которая переводит человекочитаемые команды в машинные коды. Там даже ast дерево не надо строить. Достаточно замены слов на циферки. И скорость там тоже нафиг не нужна.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 4)
Ответ на: комментарий от peregrine

даже ast дерево не надо строить. Достаточно замены слов на циферки.

Автокод 1:1, который сам даже простейшее адресное выражение не может вычислить? Зачем на такое тратить машинное время и перфокарты переводить?!

algo
()
Последнее исправление: algo (всего исправлений: 1)
Ответ на: комментарий от algo

AST дерево ассемблеру не нужно для этого. Он слишком прост, а инструкции процессора/мк слишком ограничены, чтоб были какие-то сложные выражения писать.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 2)
Ответ на: комментарий от Jullyfish

:1000_ это sub (как-то не вписывается в восмеричное, ну ладно), _0011 это R3.

MSP гораздо более шестнадцатеричная машина, чем PDP-11 и традиционные 16- и 32-разрядные x86, потому что у него 16 естественно закодированных РОН, а не 8, как на x86 и PDP-11

algo
()
Ответ на: комментарий от algo

Нет. Потому что важны не те инструкции в которые переводят код, а те которые человек пишет. На ассемблере ты не напишешь инструкций, которые могут быть написаны на языках высокого уровня.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

Но можешь написать адресные и константные выражения, которые умеет вычислять приличный ассемблер ещё на этапе ассемблерования, а часть вычислений оставить загрузчикам и компоновщикам

algo
()
Последнее исправление: algo (всего исправлений: 1)
Ответ на: комментарий от peregrine

1. абсолютный дизассемблер проще слепить чем переводчик даже тоже с абсолютными адрессами без автораскладывателя переменых в бинарные(маш)кОды

ващет ассемблеры ассемблеру рознь

т.е. саммый простейший переводит трёхбуквия в опкоды и меняет системы счисления(что ващет тоже опция) у аргументов - ну и если у проца кривая система аргов асм забирает на себя учёт этих не однородностей

далее макры

далее всякие структурные ассемблеры

вплоть до того что настоящий расшыряемый ассемблер профессионального уровня позволяет в качестве входного языка нечтно уровня Си/Паскаля с полным ооп

просто обычно от асма ожидается взаимоднозначное соответсвие машкода и стоки мнемокода если это не директива ассемблера

в какой то момент оказалось практчней перестать считать «библиотеку расширяющую HLL» а сделать отдельный траслятор ( не случайно Сяшки транслировали не машкод а мнемоники и директивы as)

qulinxao3 ★☆
()
Ответ на: комментарий от qulinxao3

не случайно Сяшки транслировали не машкод а мнемоники и директивы as

Потому что as уже был в UNIX с самого начала, и даже раньше.

А первоначальный формат объектного модуля в UNIX это и был выхлоп as ( a.out )

algo
()
Ответ на: комментарий от algo

там ещё bcpl пробегал

суть именно в том что когда ассемблер был на коне не было такой чёткой как ща границы между hll и дизасемблерным выхлопом без даже таблицы имён адрессов

ибо хорошо развитый промышленный ассемблер от hll отличался только прибитостью к опкодам целевой машины всё остальное - т.е. хитрые структуры управления и определения типов данных присутствовали - т.е. настоящему ассемблеру было что компилировать и оптимизировать :)

qulinxao3 ★☆
()

ОСТОРОЖНО!!! Творчество Алисы !!!

(mspdebug) mw 0x0200 0x41 0x00 0x22 0x00 0x01 0x00 0x21 0x00 0xff 0x3f
(mspdebug) set pc 0x0200
(mspdebug) run

Почувствуй себя настоящим опкодером!

algo
()
Ответ на: комментарий от Jullyfish

Судя по коду, инструкция 8321₁₆ должна вычитать 2 из SP(R1).

Мнемоника SUB.W #2, SP или DECD SP подходит по смыслу.

А как эта инструкция работает на Вашем устройстве?

algo
()
Ответ на: комментарий от Jullyfish

Варианты вычитания из SP

(mspdebug) dis 1000 34
0x0200:
    00200: 21 83                     DECD    SP
    00202: 01 82                     SUB     SR,     SP
    00204: 11 82 31 82               SUB     &0x8231, SP
    00208: 31 82                     SUB     #0x0008, SP
    0020a: 21 82                     SUB     #0x0004, SP
    0020c: 01 83                     SUB     #0x0000, SP
    0020e: 11 83                     DEC     SP
    00210: 31 83                     SUB     #0xffff, SP
    00212: 01 84                     SUB     R4,     SP
    00214: 11 84 21 84               SUB     0x8421(R4), SP
    00218: 31 84                     SUB     @R4+,   SP
    0021a: 21 84                     SUB     @R4,    SP
vM ★★★
()
Ответ на: комментарий от vM
(mspdebug) md 1040 2
    00220: 44 33                                           |D3              |
(mspdebug) md 1044 2
    00224: 11 22                                           |."              |
(mspdebug) regs
    ( PC: 00200)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 09990)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00005)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x0200:
    00200: 21 83                     DECD    SP
    00202: 01 82                     SUB     SR,     SP
    00204: 11 82 24 02               SUB     &0x0224, SP
    00208: 31 82                     SUB     #0x0008, SP
    0020a: 21 82                     SUB     #0x0004, SP
    0020c: 01 83                     SUB     #0x0000, SP
    0020e: 11 83                     DEC     SP
(mspdebug) step
    ( PC: 00202)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 0998e)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00005)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x0202:
    00202: 01 82                     SUB     SR,     SP
    00204: 11 82 24 02               SUB     &0x0224, SP
    00208: 31 82                     SUB     #0x0008, SP
    0020a: 21 82                     SUB     #0x0004, SP
    0020c: 01 83                     SUB     #0x0000, SP
    0020e: 11 83                     DEC     SP
    00210: 31 83                     SUB     #0xffff, SP
(mspdebug) step
    ( PC: 00204)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 09989)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00005)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x0204:
    00204: 11 82 24 02               SUB     &0x0224, SP
(mspdebug) step
    ( PC: 00208)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 07778)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00101)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x0208:
    00208: 31 82                     SUB     #0x0008, SP
    0020a: 21 82                     SUB     #0x0004, SP
    0020c: 01 83                     SUB     #0x0000, SP
    0020e: 11 83                     DEC     SP
    00210: 31 83                     SUB     #0xffff, SP
    00212: 01 84                     SUB     R4,     SP
    00214: 11 84 24 02               SUB     0x0224(R4), SP
(mspdebug) step
    ( PC: 0020a)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 07770)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00001)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x020a:
    0020a: 21 82                     SUB     #0x0004, SP
    0020c: 01 83                     SUB     #0x0000, SP
    0020e: 11 83                     DEC     SP
    00210: 31 83                     SUB     #0xffff, SP
    00212: 01 84                     SUB     R4,     SP
    00214: 11 84 24 02               SUB     0x0224(R4), SP
    00218: 31 84                     SUB     @R4+,   SP
(mspdebug) step
    ( PC: 0020c)  ( R4: 0fffc)  ( R8: 0ffff)  (R12: 0ffff)
    ( SP: 0776c)  ( R5: 0ffff)  ( R9: 0ffff)  (R13: 0ffff)
    ( SR: 00001)  ( R6: 0ffff)  (R10: 0ffff)  (R14: 0ffff)
    ( R3: 00058)  ( R7: 0ffff)  (R11: 0ffff)  (R15: 0ffff)
0x020c:
    0020c: 01 83                     SUB     #0x0000, SP
vM ★★★
()
Ответ на: комментарий от algo

mw 0x0200 0x41 0x00 0x22 0x00 0x01 0x00 0x21 0x00 0xff 0x3f

Творчество Алисы:

(mspdebug) dis 0x300
0x0300:
    00300: 41 00                     RRCM.A  #0x0001, SP
    00302: 22 00 01 00               MOVA    &0x0001, SR
    00306: 21 00 ff 3f               MOVA    &0x3fff, SP

инструкции из 20-битного расширения.

До бесконечного цикла не доходит, если начинать не с него

(mspdebug) dis 0x308 2
0x0308:
    00308: ff 3f                     JMP     0x0308
vM ★★★
()
Ответ на: комментарий от vM

00214: 11 84 21 84 SUB 0x8421(R4), SP

00218: 31 84 SUB @R4+, SP

Два важных частных случая, знакомые по PDP-11:

00280: 31 80 12 01               SUB     #0x0112, SP

00284: 11 80 11 00               SUB     0x0297, SP
algo
()
Ответ на: комментарий от vM

Варианты вычитания из SP

У вас тут и эмулируемые команды. ИМХО, немного лишнее в данном случае.

Начал писать транслятор (пока только комментарии :^) ). Очень прикольно. Я команду MOV рассмотрел. Получается, что есть сама команда (opcode 4 бита), есть операнды (S-reg, D-reg по 4 бита), и 3 (назову так) модификатора: B/W (1 бит, мнемонически цепляют к команде MOV), и режим адресации (As 2 бита b Ad 1 бит, и цепляют уже к операндам).

Jullyfish
() автор топика
Ответ на: комментарий от Jullyfish

https://github.com/smtlaissezfaire/bcompiler

попробуй раскуричающийся транслятор написать

т.е что бы твой жи асм сырец создавал бинарь чьё примение к сырцу даст тот же бинарь - чисто как критерий насколько мало подмножество команд достаточных для воплощения вполне полезных бинарей - т.е. очередное подтверждение насколько набор команд процессоров очень специфически заточен под текущие распределение прикладных задач

qulinxao3 ★☆
()

Вообще, если сократить этот код до 36 байт, удалив всё начиная с адреса 0xe022 включительно:

@e000
21 83 B2 40 80 5A 20 01 F2 D3 22 00 F2 E3 21 00 
B1 40 10 27 00 00 91 83 00 00 81 93 00 00 FB 23 
F5 3F 
@fffe
00 E0 
q

Визуально в мигании ничего не меняется. Во всевозможных примерах на msp430, а также в куче README файлах, которые поставляются с компиляторами пишут, что первым делом надо отключать watchdog. В данной программе это происходит по адресу 0xe002.

То что делалось с адреса 0xe022 до CALL 0xe000 очень похоже на стековые приколы от гнутого компилятора. Наверное 0xe022_start, а 0xe000main.

Jullyfish
() автор топика
Ответ на: комментарий от algo

Похоже нужна. А ещё всё остальное, похоже, тоже нужно. Потому что если целиком отключить питание и включить заново, то выходит фигня. Видимо, когда делаю erase, RAM остаётся в том состоянии в котором была.

Jullyfish
() автор топика

Есть команда:

B2 40 80 5A 20 01
MOV     #0x5a80, &0x0120
WDTCTL = WDTPW | WDTHOLD;

Если разложить 80 5a и 20 01 – операнды. Тут вопросов нет.

А вот B2 40, если разложить в бинарный вид, вызывает вопросы. 0x40 == 0100_0000 где 0100_ - opcode команды mov, а _0000 – src.

А вот 0xB2 == 1011_0010, вызывает вопросы:

  • 1: Indexed. The operand is in memory at address Rn+x. Тут вопросов нет, в src у нас 0000, т.е. Rn == 0, а x == 0x0120.
  • 0: Обозначает, что мы двигаем слово. Тут вопросов тоже нет.
  • 11: Register indirect. The operand is in memory at the address held in Rn, then the register is incremented by 1 or 2.
  • 0010: dst.

На последних двух пунктах пока затык.

Тут регистр R2, который по совместительству является SR, а также CR в данном случае случае используется для занесения константы.

Копи-паста с Wikipedia:

Addressing modes using R2 (SR) and R3 (CG), special-case decoding

01	1	2 (SR)	&ADDR	Absolute. The operand is in memory at address x.
10	—	2 (SR)	#4	Constant. The operand is the constant 4.
11	—	2 (SR)	#8	Constant. The operand is the constant 8.
00	—	3 (CG)	#0	Constant. The operand is the constant 0.
01	—	3 (CG)	#1	Constant. The operand is the constant 1. There is no index word.
10	—	3 (CG)	#2	Constant. The operand is the constant 2.
11	—	3 (CG)	#−1	Constant. The operand is the constant −1.

Не понимаю что значит #4, #8 (мой случай), #0 и т.д. В данном случае в &0x0120 заносится #0x5a80

Jullyfish
() автор топика
Ответ на: комментарий от algo

В общем, если залить сначала полную прошивку, а потом совсем урезанную:

@e000
B2 40 80 5A 20 01 F2 D3 22 00 F2 E3 21 00 B1 40
10 27 00 00 91 83 00 00 81 93 00 00 FB 23 F5 3F 
@fffe
00 E0 
q

Работает. А если отключить питание и включить, то не работает (точнее работает, но не так).

Мораль: при работе с MCU надо взять за правило отключать и включать питание.

Jullyfish
() автор топика
Последнее исправление: Jullyfish (всего исправлений: 1)
Ответ на: комментарий от Jullyfish

Есть подозрение, что тут википедию не стоит читать, ибо в datasheet (table 3-3), это дело выглядит более вразумительно:

As/Ad Addressing Mode        Syntax Description
00/0  Register mode          Rn     Register contents are operand
01/1  Indexed mode           X(Rn)  (Rn + X) points to the operand. X is stored
                                    in the next word.
01/1  Symbolic mode          ADDR   (PC + X) points to the operand. X is stored
                                    in the next word. Indexed mode X(PC) is
                                    used.
01/1  Absolute mode          &ADDR  The word following the instruction contains
                                    the absolute address. X is stored in the
                                    next word. Indexed mode X(SR) is used.
10/-  Indirect register mode @Rn    Rn is used as a pointer to the operand.
11/-  Indirect autoincrement @Rn+   Rn is used as a pointer to the operand. Rn
                                    is incremented afterwards by 1 for .B
                                    instructions and by 2 for .W instructions.
11/-  Immediate mode         #N     The word following the instruction contains
                                    the immediate constant N. Indirect
                                    autoincrement mode @PC+ is used.
Jullyfish
() автор топика
Ответ на: комментарий от Jullyfish

тут википедию не стоит читать,

Википедию стоит использовать для списка первоисточников.

О по микроконтроллерам приходится читать и общую документацию по семейству, и datasheet’ы конкретных моделей, и errata…

algo
()

Так, получилось всё же уменьшить исходный текстовый файл до:

@e000
31 40 fe 03 B2 40 80 5A 20 01 F2 D3 22 00 F2 E3
21 00 B1 40 10 27 00 00 91 83 00 00 81 93 00 00
FB 23 F5 3F
@fffe
00 E0 
q

Первую команду 21 83 (DECD SP) заменил на 31 40 fe 03 (MOV #0x3fe SP), а всё что до этого было начиная с адреса 0xe022 удалил.

Если в SP занести #0x400, работать не будет. Поищу ответ в datasheet.

Jullyfish
() автор топика
Ответ на: комментарий от Jullyfish

Если всё правильно понял, картина следующая:

RAM начинается с 0x200, у msp430g2553 512 (0x200) байт RAM. Т.е. RAM находится по адресам 0x2000x3fe включительно.

Jullyfish
() автор топика
Ответ на: комментарий от Jullyfish

91 83 00 00 81 93 00 00

Тут же используется ка счетчик вершина стека.

Если на 0x400 нет RAM, то не будет работать, как задумано.

Зачем нас использовать стек, если есть куча регистров?

algo
()
Ответ на: комментарий от algo

91 83 00 00 81 93 00 00

Тут же используется ка счетчик вершина стека.

Как счётчик? Тут же просто уменьшение значения по адресу в стеке и затем тестирование оного.

DEC     0x0000(SP)
TST     0x0000(SP)

Если на 0x400 нет RAM, то не будет работать, как задумано.

Да.

Зачем нас использовать стек, если есть куча регистров?

Ну-с, программу не я писал, она поставляется с MSPFlasher. Я её просто разбираю. Даже как-то получается. :^)

Jullyfish
() автор топика
Ответ на: комментарий от Jullyfish

Тут же просто уменьшение значения по адресу в стеке и затем тестирование оного.

DEC     0x0000(SP)
TST     0x0000(SP)

Что нам мешает уменьшать значение в регистре и тестировать оное?

DEC R5
TST R5
algo
()
Ответ на: комментарий от algo

TST после DEC вообще лишний, флаги установятся по результату декремента. Это и в PDP-11 так же было.

alegz ★★★★★
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария