ARM Assembly - T.I. Robotics System Learning Kit - Lab 3

About: Have enjoyed a mostly fun ride in an electronics and software career. Also enjoy latin dancing.

This Instructable has several purposes. Some specific, some general.

  • elaborate and expand more on Lab 3 of the course/kit
  • diving deeper into micro-controllers
  • detail some steps to learning assembly
  • improving higher-level language skills because of increased knowledge of lower layers

While you might get more out of this if you have the MSP432, perhaps you'll find some nugget of information or insight by just perusing the contents of this Instructable.

The MSP432 development board itself is relatively inexpensive at around $27 USD. You don't have to get the complete robotics kit. The board comes with a lot digital and analog input/output ports exposed, and supports various communications protocols. There are "hats" or add-on boards available. You can check with Amazon, Digikey, Newark, Element14, Mouser.

The Texas Instruments Robotics course includes many opportunities for hands-on learning. There are some Instructables related to this ongoing series that are more general, such as the one on capacitors, or the one to make a simple pulse generator.

The Main Issue

As of this writing (Sept 2018), the T.I. Code Composer Studio (built on Eclipse) is version 8. When creating a new CCS project, if you want to create an "assembly" (instead of C) project, it does not offer a starter template. You are able to create such a project if you select a generic micro controller, but not for the MSP432.

The Second Issue

For anyone who is doing the T.I. Robotics course, I don't think it explained or demonstrated enough of the assembly portion, at least for Lab 3. I thought it would be good to expand more on that section, with some good hands-on activities.

When learning assembly, or just wanting to quickly dive into it with the specific processor (MSP432) and version 8 of the Studio, it would be good not to have to fight to just get a project started.

Thus, this Instructable. Let's create a ready-to-go assembly project, and then let's experiment with some assembly code.

Step 1: Resources to Assist Creating an Assembly Project

As stated, you can't really create a new assembly project by just following the Composer Studio's (CCS) new-project wizard. It will only offer C programming templates for the MSP432. Again, I'm referring to version 8 of the studio, the latest on as of this writing.

I'm not going to go into installation of the studio itself. You can use the link to the T.I. course given in the introduction section in this Instructable. If you can find your way to "Module 1" of the course, this document will guide you not only to the installation of the CCS (IDE) , but also to installing and importing the many projects related to the course.

Another suggestion is to install the SDK examples. These are not the same as the course-related projects mentioned in the "Module 1" lab (installation of CCS).

The best examples that I found that did include assembly specific to the MSP432 were from the author and professor Johnathan Valvano. Texas Instruments seems to have collaborated with him to produce the TI-RSK Robotics System Learning Kit and course. Here is the code zip file; hopefully this link will be good for some time in the future.

So we're going to have to create one from an existing project.

It is from these projects that you can put together an assembly project, as I did for this Instructable.

Step 2: Let's Start.... We Compare Assembly to C Programming

Really, in Eclipse, just copy one of the existing assembly projects, and rename your new project.

I chose the "Simple Project" as a starter template, and gutted / removed most of what's in the assembly "main.asm".

If you notice the image above labeled "Simple AssemblyProject", look at all the required files. Or at least the files that came with the project. I don't know enough to try to weed out any unnecessary files, so we'll just leave them there. As mentioned in the previous step, just take an existing "asm" project (not a "C" project).

Now we take a look the really the only file we'll need to deal with, "main.asm".

Here's a most basic assembly program:

	.thumb
	.data
       .text
       .align 2
       .global  main
main:  .asmfunc
loop	B loop
       .endasmfunc
       .end

The above is the complete contents of "main.asm" for our starting very basic program. The only part that is mine, is the "loop B loop".

All of the rest of the contents are required directions to correctly go through the process of creating a valid executable piece of code that will be "burned" into the MSP432.

So what does the above program do? It just loops. It's the most tightest of loops.

If you were to debug this program and set a break point at the "loop" line, and watch the MPU's registers, such as the program counter, you wouldn't see much.

Here below is the memory map where the program code resides.

loop, main	0000E7FE	C6C00F00	F0FF002D	000004AD
00000591	000005B8	20000000	FFFFFFFF
FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF
FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF
FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF
FFFFFFFF

The memory map of the area (got the address from the program counter) seems to indicate a very small program.

Next, let's enhance our assembly program just a tad. We will add two things to it:

  • set a MCU register (register 0) (R0) to all zeros, before we enter the loop,
  • within the loop we'll have that register increment it's value (starting from zero of course)

Ok, here's the update version of the assembly program:

	.thumb
       .data
       .text
       .align 2
       .global  main
main:  .asmfunc		; The following instruction means
			; load a zero into the register R0.
			; So direction of movement is
			; from right to left.
	MOV R0,#0
loop	ADD R0,#1	; This means add 1 to the contents
	B loop
       .endasmfunc
       .end

I hope you saw that semi-colons (";") are comment lines. Below is the new contents of the memory map where the program code is. Now it seems a bit more interesting.

0000F04F
loop
0001F100	2001E7FC	BF004770
$C$L1
0000E7FE	C6C00F00	F0FF002D	000004AD
00000591	000005C0	20000000	FFFFFFFF
FFFFFFFF	FFFFFFFF	FFFFFFFF	FFFFFFFF

If you take a look at the above video "MSP432 Assembly Increment Register Loop", you can see it in action as we single-step through the code.

Now, let's try to write an equivalent "C" version of that tight loop. I'm not going to go into how to create a "C" project in the Code Composer; there are plenty of online resources for that. But, after creating an empty project with just a "main.c", we get the following, and I added the 'for()' loop with counter-increment.. (below)

#include "msp.h"

void main(void)
{
	int a = 0;
	for(;;) {
	    a++;
	}
}

Now let's take a look at the equivalent assembly code list that was generated when we built the "C" project.

          main:
2000              MOVS      A1, #0      
9000              STR       A1, [SP, #0]
          ||$C$L1||:    
9800              LDR       A1, [SP, #0]
1C40              ADDS      A1, A1, #1  
9000              STR       A1, [SP, #0]
E7FB              B         ||$C$L1||  
 

Now let's take a look at a memory map of one run of the progam:

main
0D08F1AD 90002000
$C$L1
1C409800 E7FB9000
__TI_decompress_none
2003F8D0 46081DC3 F7FF4619 B508BF31 FED0F7FF BFD0F7FF E7FEBD08
_system_pre_init
47702001
C$EXIT, abort
E7FEBF00 00000000 C6C00F00 F0FF002D 000004B5 000005A9 000005D0 20000000

Please review the "MSP432 C Prog Increment Variable Loop" video for the action.

What If We Use 'Register' Reserved Word?

So we take the above "C" program, but we add "register" in front of the "int a = 0;" line.
#include "msp.h"
void main(void)
{
	register int a = 0;
	for(;;) {
	    a++;
	}
}
Here is the generated assembly listing for the change.
          main:
2000              MOVS      A1, #0    
          ||$C$L1||:    
1C40              ADDS      A1, A1, #1
E7FD              B         ||$C$L1|| 

And here is the memory space of one run of the program:
main
1C402000 2001E7FD BF004770
$C$L1
0000E7FE 00000000 C6C00F00 F0FF002D 000004B5 00000599 000005C8 20000000
One of the images with this Step is a visual comparison of the C program that does NOT use the reserved "register" word, versus the one that does use it. I hope you can see the difference. In the second video, I hope it was clear that there were two entities incrementing values; the register R0, and the memory location associated with our "a" variable. It seems a very minor point, but I just wanted to show how being more familiar with the underlying workings of what happens when you build and a run a program written in a high-level language, could affect how efficiently is the final machine code that is actually run by the micro-controller. And how big or how small is the memory foot-print.

Step 3: Let's Expand Our Assembly Skills a Bit More...

The first video in this section demonstrates a more interesting version of the loop program in C, showing how it is possible to step through both the C code and the Assembly instructions, to gain a better understanding of what is happening.

We can also see the MPU's registers.

(please see attached video).

Comparisons, Conditional Branching, Looping

Just like with any program in any language, we would want our code do different things, and follow different paths through the code, depending on if a condition is met or not. If you have done any programming at all or looked at some code, then you're familiar with statements that look like this (these not in any order; they are just individual snippets of pseudo-code):

  • if ( ) then ..... do something
  • else do something else
  • if ( ) then go here , or break out of this loop
  • start the loop over again
  • increment some variable if you want to keep track of the number of times something occurs
  • do a test repeatedly, but check for something different every time

Each of the above statements boil down to some assembly instruction or set of instructions. Let's learn a bit more.

The Assembly Coding Challenge

Write an assembly program that will run through a series of values, test each value to see if it is a letter (anything between "A" through "Z"), and keep a count of how many values were letters, and how many values were NOT letters.

If you decide to try it, a slightly more complicated version of the above would include also testing that the values may fall between "a" through "z", inclusive.

Even if you don't have the MSP432, these instructions look very familiar and they would translate easily to another processor's instruction set.

Some Resources

Something helpful to have is an ASCII table. (see attached image to this step).

Another helpful resource talks about some of these instructions for the MSP432, or any ARM processor. In case that link fails in the future, here's some of the info:

"A beneficial feature of the ARM architecture is that instructions can be made to execute conditionally. This is common in other architectures’ branch or jump instructions but ARM allows its use with most mnemonics.
The condition is specified with a two-letter suffix, such as EQ or CC, appended to the mnemonic. The condition is tested against the current processor flags and if not met the instruction is treated as a no-op. This feature often removes the need to branch, avoiding pipeline stalls and increasing speed. It can also increase code density. By default the data processing instructions do not affect the condition code flags but can be made to by suffixing S. The comparison instructions CMP, TST, and co. do this implicitly."

Code	Suffix	Description	Flags
0000	EQ	Equal / equals zero	Z
0001	NE	Not equal	!Z
0010	CS / HS	Carry set / unsigned higher or same	C
0011	CC / LO	Carry clear / unsigned lower	!C
0100	MI	Minus / negative	N
0101	PL	Plus / positive or zero	!N
0110	VS	Overflow	V
0111	VC	No overflow	!V
1000	HI	Unsigned higher	C and !Z
1001	LS	Unsigned lower or same	!C or Z
1010	GE	Signed greater than or equal	N == V
1011	LT	Signed less than	N != V
1100	GT	Signed greater than	!Z and (N == V)
1101	LE	Signed less than or equal	Z or (N != V)
1110	AL	Always (default)	any

What does all the above mean? How can we use this information? Essentially, it boils down to this:

For any of those "suffixes" above, one thing you can do is a conditional branch to another part of the code.

Soo.. "BGE" means "branch if greater than or equal to". Another example would be "BLT". That means "branch if less than".

Final resource: a suggestion. Just use the processor's registers to run values, to do the comparison, and to keep track of how many were letters and how many were not.

The second video in this step is just one solution to the above challenge. It demonstrates the program in action and single-steps through it.

Step 4: Conclusion

We played around a bit with assembly and compared it to a higher-level language, and saw some effects of trying different things.

We saw that having a decent development environment, depending on it's abilities, can give us some insight into what's really going on down at the "bare metal".

We learned to utilize some of the MSP432's ARM instructions.

I think that even though we may not ever really start building 'real' programs in assembly, it can be worthwhile to at least get a closer look at what is the MCU really running, compared to the code we wrote. I think it will help us think more about the code that we do write.

Share

    Recommendations

    • Plastics Contest

      Plastics Contest
    • Optics Contest

      Optics Contest
    • Make it Glow Contest 2018

      Make it Glow Contest 2018

    Discussions