User Tools

Site Tools


programming_the_wisp_under_linux

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

programming_the_wisp_under_linux [2018/07/11 08:25] (current)
Line 1: Line 1:
 +====== Programming the WISP under Linux ======
 + This page is a tutorial for setting up your Ubuntu environment for compiling and debugging the WISP firmware using the USB key debugger.\\ ​ Questions? - [[http://​www.wikispaces.com/​user/​view/​melsabagh|{{http://​www.wikispaces.com/​user/​pic/​melsabagh-lg.jpg?​16x16|melsabagh}}]] [[http://​www.wikispaces.com/​user/​view/​melsabagh|melsabagh]] maintains this page.\\ \\ 
 +==== Step1: Installing MSPGCC and MSPDebug ====
 +\\  First, we need to install required build prerequisites. Open Terminal, and paste the following:​\\ ​
 +  sudo apt-get install subversion gcc-4.4 texinfo patch libncurses5-dev zlibc zlib1g-dev libx11-dev libusb-dev libreadline6-dev
 +Now, we will checkout the MSPGCC source code from the repository, and then build and install it\\ 
 +  svn checkout https://​mspgcc4.svn.sourceforge.net/​svnroot/​mspgcc4
 +  cd mspgcc4
 +  sudo sh buildgcc.sh
 +To make MSPGCC accessible by other tools, we need to add it to the environment path variables by editing the /​etc/​environment file:​\\ ​
 +  sudo nano /​etc/​environment
 +Append ":/​opt/​msp430-gcc-4.4.3/​bin"​ to the end of the PATH variable, and reload the environment file by executing:​\\ ​
 +  source /​etc/​environment
 +Next, we need to download and install MSPDebug. Land [[http://​sourceforge.net/​projects/​mspdebug/​files/​|here]] and download the latest version (mspdebug-0.13.tar.gz is used here), then execute the following:​\\ ​
 +  tar xvfz mspdebug-0.13.tar.gz
 +  cd mspdebug-0.13
 +  make
 +  sudo make install
 +Now, our environment is ready to communicate with the USB key. Just one final step which is to allow user access to the USB interface. To do so, we need to first get the vendor and product IDs of the USB key. So, attach it, and execute '​lsusb'​. This should list all available USB interfaces. Note the ID <​vendor>:<​product>​ of the USB key down (the default is 0451:f430, but yours might be different). Now, make a new udev rule:​\\ ​
 +  sudo nano /​etc/​udev/​rules.d/​wisp_usb_key_debugger.rules
 +Add the following to the new rule file, after changing PRODUCT_ID to match that of your USB key\\ 
 +  ATTRS{idVendor}=="​0451",​ ATTRS{idProduct}=="​PRODUCT_ID",​ MODE="​0660",​ GROUP="​plugdev"​
 +And then restart udev\\ ​
 +  sudo restart udev
 +Finally, check if MSPDebug can detect the usb key correctly by running:​\\ ​
 +  mspdebug uif -d /​dev/​ttyUSB0
 +If all went okay, proceed to the next step. Otherwise, revise the steps carefully and make sure you are using the correct PRODUCT_ID in your udev rule.\\ \\ \\
 +----
 +\\ 
 +==== Step2: Installing and configuring Eclipse-CDT ====
 +\\  To install Eclipse CDT, use the following command:​\\ ​
 +  sudo apt-get install eclipse-cdt
 +=== **Step2 (a) : Configuring Eclipse to use MSPGCC** ===
  
 +  - Create a new C++ project (we will give it the name '​wisp_41_mspgcc'​).
 +  - Click on '​Project->​Properties'​ menu item, and expand the 'C/C++ Build' node in the left panel.
 +  - Select '​Discovery Options'​ from the left panel.
 +  - For each of the compilers in the '​Tools'​ list, type '​msp430-gcc'​ in the '​Compiler invocation command'​ field.
 +  - Select the '​Settings'​ node from the left panel.
 +  - For each of the 'GCC C++ Compiler',​ 'GCC C Compiler'​ and 'GCC C++ Linker',​ type '​msp430-gcc -mmcu=msp430x2132'​ in the '​command'​ field.
 +  - For the 'GCC Assembler'​ type '​msp430-as'​ in the '​command'​ field.
 +  - Under the 'GCC C++ Linker',​ select '​Libraries'​ and add the following to the '​Library search path':
 +   
 +  * /​opt/​msp430-gcc-4.4.3/​lib
 +   
 +  * /​opt/​msp430-gcc-4.4.3/​msp430/​lib
 +  - Select the 'Build Artifact'​ tab, and type '​elf'​ in the '​Artifact extension'​ field.
 +  - Select '​Binary Parser'​ tab, and make sure the 'ELF parser'​ is checked.
 +  - Apply all, press Okay, and close the project properties window.
 +\\ 
 +=== **Step2 (b) : Configuring Eclipse to work with MSPDebug** ===
 +
 +  - Open '​Run->​External Tools->​External Tools Configurations'​
 +  - Click on 'New launch configuration',​ and use the following parameters
 +   
 +  * Name: mspdebug gdb loop
 +   
 +  * Location: /​usr/​local/​bin/​mspdebug
 +   
 +  * Working Directory: ${project_loc}/​Debug
 +   
 +  * Arguments: uif -d /​dev/​ttyUSB0 gdb
 +  - Apply, press Okay, and close the wizard.
 +  - Open '​Run->​Debug Configurations',​ and click on 'New launch configuration'​.
 +  - In the '​Arguments'​ tab, deselect 'Use default'​ and change the '​Working directory'​ to:
 +   
 +  * ${workspace_loc:​project_name/​Debug}
 +  - In the debugger tab, select '​gdbserver Debugger'​ from the '​Debugger'​ dropbox.
 +  - In the '​Debugger Options'​ section, use the following parameters for the '​Main'​ options:
 +   
 +  * GDB debugger: msp430-gdb
 +   
 +  * GDB command file: .gdbinit
 +   
 +  * GDB command set: standard
 +   
 +  * Protocol: mi
 +  - For the '​Connection'​ options, use the following parameters:
 +   
 +  * Type: TCP
 +   
 +  * Host name or IP address: localhost
 +   
 +  * Port number: 2000
 +  - Now, add the firmware source and headers to your project, and change the file extension of hw41_D41 from .c to .cpp.
 +  - Finally, go to the root directory of your project, create a new file called '​.gdbinit'​ with the following content:
 +  set remotetimeout 999999
 +  load Debug/​wisp_41_mspgcc.elf
 +\\ \\
 +----
 +==== **Step3: Patching the firmware source** ====
 +\\ MSPGCC requires some specific style of inline asm, pragmas, and interrupt handlers. To modify the firmware source code to work with MSPGCC, you can save and apply the following patch:​\\ ​
 +  --- hw41_D41.cpp 2009-03-06 12:​31:​16.000000000 +0200
 +  +++ hw41_D41_mspgcc.cpp ​   2011-01-01 16:​04:​58.246979000 +0200
 +  @@ -139,6 +139,12 @@
 +   #​define TID_DESIGNER_ID_AND_MODEL_NUMBER ​ 0xFF, 0xF0, 0x01
 +   ////////////////////////////////////////////////////////////////////////////////​
 +
 +  +
 +  +#ifndef __MSP430__//​ TODO: REMOVE IF NOT mspgcc compiler
 +  +  #define __MSP430__
 +  +  #include <​signal.h>​
 +  +#endif
 +  +
 +   #​if(WISP_VERSION == BLUE_WISP)
 +     #​include <​msp430x21x2.h>​
 +     #​include "​pinDefWISP4.1DL.h"​
 +  @@ -194,8 +200,6 @@
 +   #​define SEND_CLOCK ​ \
 +     ​BCSCTL1 = XT2OFF + RSEL3 + RSEL0 ; \
 +       ​DCOCTL = DCO2 + DCO1 ;
 +  -  //BCSCTL1 = XT2OFF + RSEL3 + RSEL1 ; \
 +  -  //DCOCTL = 0;
 +   #​define RECEIVE_CLOCK \
 +     ​BCSCTL1 = XT2OFF + RSEL3 + RSEL1 + RSEL0; \
 +     ​DCOCTL = 0; \
 +  @@ -211,9 +215,9 @@
 +   // #pragma data_alignment=2 is important in sendResponse() when the words are copied into arrays.
 +   // Sometimes the compiler puts reply[0] on an
 +   // odd address, which cannot be copied as a word and thus screws everything up.
 +  -#pragma data_alignment=2
 +  +///#pragma data_alignment=2
 +
 +  -volatile unsigned char queryReply[]= { 0x00, 0x03, 0x00, 0x00};
 +  +volatile unsigned char queryReply[] __attribute__ ((aligned(2))) = { 0x00, 0x03, 0x00, 0x00};
 +
 +   // ackReply: ​ First two bytes are the preamble. ​ Last two bytes are the crc.
 +   ​volatile unsigned char ackReply[] ​ = { 0x30, 0x00, EPC, 0x00, 0x00};
 +  @@ -236,11 +240,21 @@
 +
 +   // compiler uses working register 4 as a global variable
 +   // Pointer to &​cmd[bits]
 +  +#ifdef __MSP430__
 +  +volatile register unsigned char* dest __asm__("​4"​);​
 +  +#else
 +   ​extern volatile __no_init __regvar unsigned char* dest @ 4;
 +  +#endif // __MSP430__
 +  +
 +
 +   // compiler uses working register 5 as a global variable
 +   // count of bits received from reader
 +  +#ifdef __MSP430__
 +  +volatile register unsigned short bits __asm__("​5"​);​
 +  +#else
 +   ​extern volatile __no_init __regvar unsigned short bits @ 5;
 +  +#endif // __MSP430__
 +  +
 +   ​unsigned short TRcal=0;
 +
 +   #​define STATE_READY ​              0
 +  @@ -423,7 +437,7 @@
 +   // ​ P1IES &= ~BIT2; // initial state is POS edge to find start of CW
 +   // ​ P1IFG = 0x00;       // clear interrupt flag after changing edge trigger
 +
 +  -  asm("​MOV #0000h, R9");
 +  +  asm("​MOV #llo(0), R9");
 +     // dest = destorig;
 +
 +   #if READ_SENSOR
 +  @@ -433,7 +447,7 @@
 +   #if !(ENABLE_SLOTS)
 +     ​queryReplyCRC = crc16_ccitt(&​queryReply[0],​2);​
 +     ​queryReply[3] = (unsigned char)queryReplyCRC;​
 +  -  queryReply[2] = (unsigned char)__swap_bytes(queryReplyCRC);​
 +  +  queryReply[2] = (unsigned char) queryReplyCRC >> 8;
 +   #​endif
 +
 +   #if SENSOR_DATA_IN_ID
 +  @@ -444,7 +458,7 @@
 +   #else
 +     ​ackReplyCRC = crc16_ccitt(&​ackReply[0],​ 14);
 +     ​ackReply[15] = (unsigned char)ackReplyCRC;​
 +  -  ackReply[14] = (unsigned char)__swap_bytes(ackReplyCRC);​
 +  +  ackReply[14] = (unsigned char) ackReplyCRC >> 8;
 +   #​endif
 +
 +   #if ENABLE_SESSIONS
 +  @@ -1827,7 +1841,7 @@
 +     P1IFG = 0;  // Clear interrupt flag
 +
 +     ​P1IE ​ |= RX_PIN; // Enable Port1 interrupt
 +  -  _BIS_SR(LPM4_bits | GIE);
 +  +  _BIS_SR((LPM4_bits) | (GIE));
 +     ​return;​
 +   }
 +
 +  @@ -1857,7 +1871,7 @@
 +     if (is_power_good())
 +       P2IFG = VOLTAGE_SV_PIN;​
 +
 +  -  _BIS_SR(LPM4_bits | GIE);
 +  +  _BIS_SR((LPM4_bits) | (GIE));
 +
 +   // ​ P1OUT |= RX_EN_PIN;
 +     ​return;​
 +  @@ -1875,8 +1889,12 @@
 +   // Pin Setup :
 +   // Description : Port 2 interrupt wakes on power good signal from supervisor.
 +
 +  +#ifdef __MSP430__
 +  +interrupt(PORT2_VECTOR) Port2_ISR (void)
 +  +#else
 +   #​pragma vector=PORT2_VECTOR
 +   ​__interrupt void Port2_ISR(void) ​  // (5-6 cycles) to enter interrupt
 +  +#endif
 +   {
 +     P2IFG = 0x00;
 +     P2IE = 0;       // Interrupt disable
 +  @@ -1890,12 +1908,16 @@
 +     ​LPM4_EXIT;​
 +   }
 +
 +  -#if USE_2132
 +  -#pragma vector=TIMER0_A0_VECTOR
 +  +#ifdef __MSP430__
 +  +interrupt (TIMER0_A0_VECTOR) TimerA0_ISR (void)
 +   #else
 +  -#pragma vector=TIMERA0_VECTOR
 +  -#endif
 +  +# if USE_2132
 +  +#  pragma vector=TIMER0_A0_VECTOR
 +  +# else
 +  +#  pragma vector=TIMERA0_VECTOR
 +  +# endif
 +   ​__interrupt void TimerA0_ISR(void) ​  // (5-6 cycles) to enter interrupt
 +  +#endif
 +   {
 +     TACTL = 0;    // have to manually clear interrupt flag
 +     ​TACCTL0 = 0;  // have to manually clear interrupt flag
 +  @@ -1910,13 +1932,17 @@
 +   // Pin Setup :  P1.2
 +   // Description : Port 1 interrupt is used as finding delimeter.
 +
 +  +#ifdef __MSP430__
 +  +interrupt (PORT1_VECTOR) Port1_ISR (void)
 +  +#else
 +   #​pragma vector=PORT1_VECTOR
 +   ​__interrupt void Port1_ISR(void) ​  // (5-6 cycles) to enter interrupt
 +  +#endif
 +   {
 +
 +   #if USE_2132
 +  -  asm("​MOV TA0R, R7"​); ​ // move TAR to R7(count) register (3 CYCLES)
 +  +  asm("​MOV %0, R7 ":: "​r"​ (TA0R));
 +   #else
 +     ​asm("​MOV TAR, R7"​); ​ // move TAR to R7(count) register (3 CYCLES)
 +   #​endif
 +  @@ -1924,37 +1950,37 @@
 +     TAR = 0;            // 4 cycles
 +     ​LPM4_EXIT;​
 +
 +  -  asm("​CMP #0000h, R5\n"​); ​         // if (bits == 0) (1 cycle)
 +  +  asm("​CMP #llo(0), R5\n"​); ​         // if (bits == 0) (1 cycle)
 +     ​asm("​JEQ bit_Is_Zero_In_Port_Int\n"​); ​               // 2 cycles
 +     // bits != 0:
 +  -  asm("​MOV #0000h, R5\n"​); ​         // bits = 0  (1 cycles)
 +  +  asm("​MOV #llo(0), R5\n"​); ​         // bits = 0  (1 cycles)
 +
 +  -  asm("​CMP #0010h, R7\n"​); ​         //​************ this is finding delimeter (12.5us) ​ (2 cycles)*********/ ​  ​2d ​ ->   14
 +  +  asm("​CMP #llo(0x10), R7\n"​); ​         //​************ this is finding delimeter (12.5us) ​ (2 cycles)*********/ ​  ​2d ​ ->   14
 +     ​asm("​JNC delimiter_Value_Is_wrong\n"​); ​           //(2 cycles)
 +  -  asm("​CMP #0040h, R7"​); ​            //​************ this is finding delimeter (12.5us) ​ (2 cycles)********* ​ 43H
 +  +  asm("​CMP #llo(0x40), R7"​); ​            //​************ this is finding delimeter (12.5us) ​ (2 cycles)********* ​ 43H
 +     ​asm("​JC ​ delimiter_Value_Is_wrong\n"​);​
 +  -  asm("​CLR P1IE"​);​
 +  +  asm("​CLR %0" : "​=r"​ (P1IE));
 +   #if USE_2132
 +  -  asm("​BIS #8010h, TA0CCTL1\n"​); ​    // (5 cycles) ​  ​TACCTL1 |= CM1 + CCIE
 +  +  asm("​BIS #​llo(0x8010),​ %0\n" : "​=r"​ (TA0CCTL1));​
 +   #else
 +  -  asm("​BIS #8010h, TACCTL1\n"​); ​    // (5 cycles) ​  ​TACCTL1 |= CM1 + CCIE
 +  +  asm("​BIS #​llo(0x8010),​ TACCTL1\n"​); ​    // (5 cycles) ​  ​TACCTL1 |= CM1 + CCIE
 +   #​endif
 +  -  asm("​MOV #0004h, P1SEL\n"​); ​      // enable TimerA1 ​   (4 cycles)
 +  +  asm("​MOV #llo(0x04), %0\n" : "​=r"​ (P1SEL));
 +     ​asm("​RETI\n"​);​
 +
 +     ​asm("​delimiter_Value_Is_wrong:​\n"​);​
 +  -  asm("​BIC #0004h, P1IES\n"​);​
 +  -  asm("​MOV #0000h, R5\n"​); ​         // bits = 0  (1 cycles)
 +  +  asm("​BIC #llo(0x04), %0\n" : "​=r"​ (P1IES));
 +  +  asm("​MOV #llo(0), R5\n"​); ​         // bits = 0  (1 cycles)
 +     ​delimiterNotFound = 1;
 +     ​asm("​RETI"​);​
 +
 +     ​asm("​bit_Is_Zero_In_Port_Int:​\n"​); ​                // bits == 0
 +   #if USE_2132
 +  -  asm("​MOV #0000h, TA0R\n"​); ​    // reset timer (4 cycles)
 +  +  asm("​MOV #llo(0), %0\n" : "​=r"​ (TA0R)); ​    // reset timer (4 cycles)
 +   #else
 +  -  asm("​MOV #0000h, TAR\n"​); ​    // reset timer (4 cycles)
 +  +  asm("​MOV #llo(0), TAR\n"​); ​    // reset timer (4 cycles)
 +   #​endif
 +  -  asm("​BIS #0004h, P1IES\n"​); ​  // 4 cycles ​ change port interrupt edge to neg
 +  +  asm("​BIS #llo(0x04), %0\n" : "​=r"​ (P1IES)); ​  // 4 cycles ​ change port interrupt edge to neg
 +     ​asm("​INC R5\n"​); ​           // 1 cycle
 +     ​asm("​RETI\n"​);​
 +
 +  @@ -1965,27 +1991,30 @@
 +   // Pin Setup :  P1.2
 +   // Description :
 +
 +  -#if USE_2132
 +  -#pragma vector=TIMER0_A1_VECTOR
 +  +#ifdef __MSP430__
 +  +interrupt (TIMER0_A1_VECTOR) TimerA1_ISR (void)
 +   #else
 +  -#pragma vector=TIMERA1_VECTOR
 +  -#endif
 +  +# if USE_2132
 +  +#  pragma vector=TIMER0_A1_VECTOR
 +  +# else
 +  +#  pragma vector=TIMERA1_VECTOR
 +  +# endif
 +   ​__interrupt void TimerA1_ISR(void) ​  // (6 cycles) to enter interrupt
 +  +#endif
 +   {
 +  -
 +  -    asm("​MOV 0174h, R7"​); ​ // move TACCR1 to R7(count) register (3 CYCLES)
 +  +    asm("​MOV #​llo(0x0174),​ R7"​); ​ // move TACCR1 to R7(count) register (3 CYCLES)
 +       TAR = 0;               // reset timer (4 cycles)
 +       ​TACCTL1 &= ~CCIFG; ​     // must manually clear interrupt flag (4 cycles)
 +
 +       //<​--------------up to here 26 cycles + 6 cyles of Interrupt == 32 cycles ---------------->​
 +  -    asm("​CMP #0003h, R5\n"​); ​     // if (bits >= 3).  it will do store bits
 +  +    asm("​CMP #llo(0x03), R5\n"​); ​     // if (bits >= 3).  it will do store bits
 +       ​asm("​JGE bit_Is_Over_Three\n"​);​
 +       // bit is not 3
 +  -    asm("​CMP #0002h, R5\n"​); ​  // if ( bits == 2)
 +  +    asm("​CMP #llo(0x02), R5\n"​); ​  // if ( bits == 2)
 +       ​asm("​JEQ bit_Is_Two\n"​); ​        // if (bits == 2).
 +
 +       // <​----------------- bit is not 2 ------------------------------->​
 +  -    asm("​CMP #0001h, R5\n"​); ​     // if ( bits == 1). it will measure RTcal value.
 +  +    asm("​CMP #llo(0x01), R5\n"​); ​     // if ( bits == 1). it will measure RTcal value.
 +       ​asm("​JEQ bit_Is_One\n"​); ​         // bits == 1
 +
 +       // <​-------------------- this is bit == 0 case --------------------->​
 +  @@ -1999,7 +2028,7 @@
 +       ​asm("​bit_Is_One:​\n"​); ​        // bits == 1.  calculate RTcal value
 +       ​asm("​MOV R7, R9\n"​); ​      // 1 cycle
 +       ​asm("​RRA R7\n"​); ​   // R7(count) is divided by 2.   1 cycle
 +  -    asm("​MOV #0FFFFh, R8\n"​); ​  // R8(pivot) is set to max value    1 cycle
 +  +    asm("​MOV #​llo(0xffff),​ R8\n"​); ​  // R8(pivot) is set to max value    1 cycle
 +       ​asm("​SUB R7, R8\n"​); ​       // R8(pivot) = R8(pivot) -R7(count/​2) make new R8(pivot) value     1 cycle
 +       ​asm("​INC R5\n"​); ​       // bits++
 +       ​asm("​CLR R6\n"​);​
 +  @@ -2017,11 +2046,12 @@
 +       ​asm("​ADDC.b @R4+,​-1(R4)\n"​);​ // roll left (emulated by adding to itself == multiply by 2 + carry)
 +       // R6 lets us know when we have 8 bits, at which point we INC dest*            // (1 cycle)
 +       ​asm("​INC R6\n"​);​
 +  -    asm("​CMP #​0008,​R6\n\n"​); ​  // undo increment of dest* (R4) until we have 8 bits
 +  +    asm("​CMP #​llo(0x08),​R6\n\n"​); ​  // undo increment of dest* (R4) until we have 8 bits
 +  +
 +       ​asm("​JGE out_p\n"​);​
 +       ​asm("​DEC R4\n"​);​
 +       ​asm("​out_p:​\n"​); ​          // decrement R4 if we haven'​t gotten 16 bits yet  (3 or 4 cycles)
 +  -    asm("​BIC #​0008h,​R6\n"​); ​  // when R6=8, this will set R6=0   (1 cycle)
 +  +    asm("​BIC #​llo(0x08),​R6\n"​); ​  // when R6=8, this will set R6=0   (1 cycle)
 +       ​asm("​INC R5\n"​);​
 +       ​asm("​RETI"​);​
 +       // <​------------------ end of bit 2 ------------------------------>​
 +  @@ -2029,7 +2059,7 @@
 +       ​asm("​this_Is_TRcal:​\n"​);​
 +       ​asm("​MOV R7, R5\n"​); ​   // bits = count. use bits(R5) to assign new value of TRcal
 +       TRcal = bits;       // assign new value     (4 cycles)
 +  -    asm("​MOV #0003h, R5\n"​); ​     // bits = 3..assign 3 to bits, so it will keep track of current bits    (2 cycles)
 +  +    asm("​MOV #llo(0x03), R5\n"​); ​     // bits = 3..assign 3 to bits, so it will keep track of current bits    (2 cycles)
 +       ​asm("​CLR R6\n"​);​ // (1 cycle)
 +       ​asm("​RETI"​);​
 +
 +  @@ -2040,11 +2070,11 @@
 +       ​asm("​ADDC.b @R4+,​-1(R4)\n"​);​ // roll left (emulated by adding to itself == multiply by 2 + carry)
 +       // R6 lets us know when we have 8 bits, at which point we INC dest*            // (1 cycle)
 +       ​asm("​INC R6\n"​);​
 +  -    asm("​CMP #​0008,​R6\n"​); ​  // undo increment of dest* (R4) until we have 8 bits
 +  +    asm("​CMP #​llo(0x08),​R6\n"​); ​  // undo increment of dest* (R4) until we have 8 bits
 +       ​asm("​JGE out_p1\n"​);​
 +       ​asm("​DEC R4\n"​);​
 +       ​asm("​out_p1:​\n"​); ​          // decrement R4 if we haven'​t gotten 16 bits yet  (3 or 4 cycles)
 +  -    asm("​BIC #​0008h,​R6\n"​); ​  // when R6=8, this will set R6=0   (1 cycle)
 +  +    asm("​BIC #​llo(0x08),​R6\n"​); ​  // when R6=8, this will set R6=0   (1 cycle)
 +       ​asm("​INC R5\n"​); ​             // bits++
 +       ​asm("​RETI\n"​);​
 +       // <​------------------ end of bit is over 3 ------------------------------>​
 +  @@ -2103,23 +2133,23 @@
 +       //​asm("​MOV #05h, R14");
 +       //​asm("​MOV #02h, R15");
 +       bits = TRext; ​      // 6 cycles
 +  -    asm("​CMP #0001h, R5"​); ​ // 1 cycles
 +  +    asm("​CMP #llo(0x01), R5"​); ​ // 1 cycles
 +       ​asm("​JEQ TRextIs_1"​); ​  // 2 cycles
 +  -    asm("​MOV #0004h, R9"​); ​  // 1 cycles
 +  +    asm("​MOV #llo(0x04), R9"​); ​  // 1 cycles
 +       ​asm("​JMP otherSetup"​); ​  // 2 cycles
 +
 +       // initialize loop for 16 M/LF
 +       ​asm("​TRextIs_1:"​);​
 +  -    asm("​MOV #000fh, R9"​); ​   // 2 cycles ​   *** this will chagne to right value
 +  +    asm("​MOV #llo(0x0f), R9"​); ​   // 2 cycles ​   *** this will chagne to right value
 +       ​asm("​NOP"​);​
 +
 +       //
 +       ​asm("​otherSetup:"​);​
 +       bits = numOfBits; ​               // (3 cycles). ​ This value will be adjusted. if numOfBit is constant, it takes 2 cycles
 +  -    asm("​MOV #0bh, R14"​); ​    // (2 cycles) R14 is used as timer value 11, it will be 2 us in 6 MHz
 +  -    asm("​MOV #05h, R15"​); ​     // (2 cycles) R15 is used as tiemr value 5, it will be 1 us in 6 MHz
 +  +    asm("​MOV #llo(0x0b), R14"​); ​    // (2 cycles) R14 is used as timer value 11, it will be 2 us in 6 MHz
 +  +    asm("​MOV #llo(0x05), R15"​); ​     // (2 cycles) R15 is used as tiemr value 5, it will be 1 us in 6 MHz
 +       ​asm("​MOV @R4+, R7"​); ​     // (2 cycles) Assign data to R7
 +  -    asm("​MOV #0010h, R13"​); ​  // (2 cycles) Assign decimal 16 to R13, so it will reduce the 1 cycle from below code
 +  +    asm("​MOV #llo(0x10), R13"​); ​  // (2 cycles) Assign decimal 16 to R13, so it will reduce the 1 cycle from below code
 +       ​asm("​MOV R13, R6"​); ​      // (1 cycle)
 +       ​asm("​SWPB R7"​); ​          // (1 cycle) ​   Swap Hi-byte and Low byte
 +       ​asm("​NOP"​);​
 +  @@ -2142,7 +2172,7 @@
 +       // if the TRext is 0, there are 4 M/LF.  If the TRext is 1, there are 16 M/LF
 +       // The upper code executed 1 M/LF, so the count(R9) should be number of M/LF - 1
 +       //​asm("​MOV #000fh, R9"​); ​   // 2 cycles ​   *** this will chagne to right value
 +  -    asm("​MOV #0001h, R10"​); ​  // 1 cycles
 +  +    asm("​MOV #llo(0x01), R10"​); ​  // 1 cycles
 +       // The below code will create the number base encoding waveform., so the number of count(R9) should be times of M
 +       // For example, if M = 2 and TRext are 1(16, the number of count should be 32.
 +       ​asm("​M_LF_Count:"​);​
 +  @@ -2172,8 +2202,8 @@
 +
 +       ​asm("​M_LF_Count_End:"​);​
 +       // this code is preamble for 010111 , but for the loop, it will only send 01011
 +  -    asm("​MOV #5c00h, R9"​); ​     // 2 cycles
 +  -    asm("​MOV #0006h, R10"​); ​    // 2 cycles
 +  +    asm("​MOV #​llo(0x5c00),​ R9"​); ​     // 2 cycles
 +  +    asm("​MOV #llo(0x06), R10"​); ​    // 2 cycles
 +       // this should be counted as 0. Therefore, Assembly DEC line should be 1 after executing
 +       ​asm("​Preamble_Loop:"​);​
 +       ​asm("​DEC R10"​); ​              // 1 cycle
 +  @@ -2183,7 +2213,7 @@
 +       // this is 1 case for preamble
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV R14, TA0CCR0"​); ​      // 4 cycle      .. 10
 +  +    asm("​MOV R14, %0" : "​=r"​ (TA0CCR0)); ​      // 4 cycle      .. 10
 +   #else
 +       ​asm("​MOV R14, TACCR0"​); ​      // 4 cycle      .. 10
 +   #​endif
 +  @@ -2191,7 +2221,7 @@
 +       ​asm("​NOP"​);​
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV R15, TA0CCR0"​); ​      // 4 cycle      .. 19
 +  +    asm("​MOV R15, %0" : "​=r"​ (TA0CCR0)); ​      // 4 cycle      .. 19
 +   #else
 +       ​asm("​MOV R15, TACCR0"​); ​      // 4 cycle      .. 19
 +   #​endif
 +  @@ -2229,7 +2259,7 @@
 +       ​asm("​NOP"​); ​   // TURN ON
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV.B R14, TA0CCR0"​);//​ 4 cycles
 +  +    asm("​MOV.B R14, %0" : "​=r"​ (TA0CCR0));//​ 4 cycles
 +   #else
 +       ​asm("​MOV.B R14, TACCR0"​);//​ 4 cycles
 +   #​endif
 +  @@ -2237,7 +2267,7 @@
 +       ​asm("​NOP"​);​
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV.B R15, TA0CCR0"​);​
 +  +    asm("​MOV.B R15, %0" : "​=r"​ (TA0CCR0));
 +   #else
 +       ​asm("​MOV.B R15, TACCR0"​);​
 +   #​endif
 +  @@ -2267,7 +2297,7 @@
 +       // bit is 1
 +       ​asm("​bit_is_one:"​);​
 +   #if USE_2132
 +  -    asm("​MOV R14, TA0CCR0"​); ​                  // 4 cycles ​  ..11
 +  +    asm("​MOV R14, %0" : "​=r"​ (TA0CCR0)); ​                  // 4 cycles ​  ..11
 +   #else
 +       ​asm("​MOV R14, TACCR0"​); ​                  // 4 cycles ​  ..11
 +   #​endif ​               // 4 cycles ​  ..11
 +  @@ -2276,7 +2306,7 @@
 +       // This code will assign new data from reply and then swap bytes. ​ After that, update R6 with 16 bits
 +       //​asm("​MOV @R4+, R7");
 +   #if USE_2132
 +  -    asm("​MOV R15, TA0CCR0"​); ​                  // 4 cycles ​  .. 20
 +  +    asm("​MOV R15, %0" : "​=r"​ (TA0CCR0)); ​                  // 4 cycles ​  .. 20
 +   #else
 +       ​asm("​MOV R15, TACCR0"​); ​                  // 4 cycles ​  .. 20
 +   #​endif
 +  @@ -2292,7 +2322,7 @@
 +       ​asm("​seq_zero:"​);​
 +       ​asm("​NOP"​); ​                        // 1 cycle   .. 3
 +   #if USE_2132
 +  -    asm("​MOV R15, TA0CCR0"​); ​        // 4 cycles ​      ..7
 +  +    asm("​MOV R15, %0" : "​=r"​ (TA0CCR0)); ​        // 4 cycles ​      ..7
 +   #else
 +       ​asm("​MOV R15, TACCR0"​); ​        // 4 cycles ​      ..7
 +   #​endif
 +  @@ -2313,7 +2343,7 @@
 +       ​asm("​JC nextBitIs1"​); ​           // 2 cycles ​ .. 20
 +       // bit is 0
 +   #if USE_2132
 +  -    asm("​MOV R14, TA0CCR0"​); ​            // 4 cycles ​ .. 24
 +  +    asm("​MOV R14, %0" : "​=r"​ (TA0CCR0)); ​            // 4 cycles ​ .. 24
 +   #else
 +       ​asm("​MOV R14, TACCR0"​); ​            // 4 cycles ​ .. 24
 +   #​endif
 +  @@ -2331,7 +2361,7 @@
 +       ​asm("​RLC R7"​); ​                       // 1 cycle     .. 18
 +       ​asm("​JC nextBitIs1"​); ​               // 2 cycles ​   ..20
 +   #if USE_2132
 +  -    asm("​MOV R14, TA0CCR0"​); ​              // 4 cycles ​  .. 24
 +  +    asm("​MOV R14, %0" : "​=r"​ (TA0CCR0)); ​              // 4 cycles ​  .. 24
 +   #else
 +       ​asm("​MOV R14, TACCR0"​); ​              // 4 cycles ​  .. 24
 +   #​endif
 +  @@ -2354,7 +2384,7 @@
 +       ​asm("​bit_Count_Is_Not_16:"​); ​      // up to here 14
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV R15, TA0CCR0"​); ​            // 4 cycles ​  .. 20
 +  +    asm("​MOV R15, %0" : "​=r"​ (TA0CCR0)); ​            // 4 cycles ​  .. 20
 +   #else
 +       ​asm("​MOV R15, TACCR0"​); ​            // 4 cycles ​  .. 20
 +   #​endif
 +  @@ -2391,7 +2421,7 @@
 +       ​asm("​NOP"​);​
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV.B R14, TA0CCR0"​);//​ 4 cycles
 +  +    asm("​MOV.B R14, %0" : "​=r"​ (TA0CCR0));//​ 4 cycles
 +   #else
 +       ​asm("​MOV.B R14, TACCR0"​);//​ 4 cycles
 +   #​endif
 +  @@ -2399,7 +2429,7 @@
 +       ​asm("​NOP"​);​
 +       ​asm("​NOP"​);​
 +   #if USE_2132
 +  -    asm("​MOV.B R15, TA0CCR0"​);​
 +  +    asm("​MOV.B R15, %0" : "​=r"​ (TA0CCR0));
 +   #else
 +       ​asm("​MOV.B R15, TACCR0"​);​
 +   #​endif
 +  @@ -2480,11 +2510,11 @@
 +     ​readReplyCRC = crc16_ccitt(&​readReply[0],​ numDataBytes + 2);
 +     ​readReply[numDataBytes + 4] = readReply[numDataBytes + 2];
 +     // XOR the MSB of CRC with loner bit.
 +  -  readReply[numDataBytes + 4] ^= __swap_bytes(readReplyCRC);​ // XOR happens with MSB of lower nibble
 +  +  readReply[numDataBytes + 4] ^= (readReplyCRC >> 8); // XOR happens with MSB of lower nibble
 +     // Just take the resulting bit, not the whole byte
 +     ​readReply[numDataBytes + 4] &= 0x80;
 +
 +  -  unsigned short mask = __swap_bytes(readReply[numDataBytes + 4]);
 +  +  unsigned short mask = (readReply[numDataBytes + 4] >> 8);
 +     mask >>= 3;
 +     mask |= (mask >> 7);
 +     mask ^= 0x1020;
 +  @@ -2493,7 +2523,7 @@
 +     ​readReplyCRC ^= mask;
 +
 +     ​readReply[numDataBytes + 3] = (unsigned char) readReplyCRC;​
 +  -  readReply[numDataBytes + 2] |= (unsigned char) (__swap_bytes(readReplyCRC) & 0x7F);
 +  +  readReply[numDataBytes + 2] |= (unsigned char) ((readReplyCRC >> 8) & 0x7F);
 +   }
 +
 +   #if 0
 +\\
 +----
 +==== **Step4: Debugging** ====
 +\\  After applying the patch, everything should compile and build successfully! You are now ready to download the firmware to the WISP and start debugging. To do so, simply proceed as follows:​\\ ​
 +
 +  - Run the '​mspdebug gdb loop' external tool
 +  - Then, press the '​Debug'​ button in the eclipse toolbar, and it will start a debug session where you can break, step in/out, etc.
 +\\ \\
 +----
 +\\ 
 +==== Other Resources ====
 +[[http://​sourceforge.net/​apps/​mediawiki/​mspgcc/​index.php?​title=Setting_up_an_IDE|MSPGCC Wiki]]\\ [[http://​www.linuxjournal.com/​article/​8682|Linux Journal - MSP430 Development with Linux]]\\ [[http://​hackaday.com/​2010/​08/​11/​how-to-launchpad-programming-with-linux/​|How to launchpad programming with Linux]]\\ \\
 +----
 +\\  The last modification was made by - [[http://​www.wikispaces.com/​user/​view/​yeagerd|{{http://​www.wikispaces.com/​user/​pic/​yeagerd-lg.jpg?​16x16|yeagerd}}]] [[http://​www.wikispaces.com/​user/​view/​yeagerd|yeagerd]] on Apr 26, 2012 9:28 am
programming_the_wisp_under_linux.txt ยท Last modified: 2018/07/11 08:25 (external edit)