1

How to declare array of constants in flash using only assembly not C?

The question says it all, I believe. Other than within the assembly code itself, I will want to access and iterate through that constant array of values.

I am using Code Composer Studio , an MSP432.

To contrast, I know how to access RAM because I know where those addresses exist, and my code is free to do whatever with them. Thus, I can do something like so:

;declare 1st RAM address:
FIRST   .field 0x20000000,32

;use it:
    LDR R1,FIRST
    LDRB R0,[R1]
;etc.

Or if I'm accessing GPIO, I know the specific input adress(es):

;declare:
PORT1INPUT    .field 0x4000C000,32
;use:
    LDR R1,PORT1INPUT
    LDRB R0,[R1]

But I want values from flash, contiguous, from known addresses, just like above.

UPDATE:

       .thumb             
       .text             
       .align  2       

;my issue or question is about this section (I think)
;don't know how or what to put here
;to declare a continguous block of
;addresses in flash, containing
;specific values

;i dont want to load just the values,
;i need to know how to start at a certain
;address
; i.e. i want to mimic an array,
; but in flash.

;i know how to initialize and mimic an
;array in RAM.

      .global main    
      .thumbfunc main  

main: .asmfunc 

mainloop
    ;code here that starts at
    ;first address in flash
    ;containing first value
    ;and reads it into a register
    ;
    ;the code isn't the problem.
    ;i know how to do this part.

    B  mainloop

    .endasmfunc     
    .end           

MORE UPDATE I create a bare-bones C project in Code Composer, for the MSP432. in main(), I have:

#include "msp.h"

static const int somearr[] = { 1,2,3,4,5,6,7};

void main(void) {
    int i = somearr[0];//needed so compiler would not ignore declaration
}

When I debugged it, turns out just like I wanted - a series of constants in flash , in this case situated after the code "main()", starting at flash address 0x000005D0. And the data stored at each consecutive location after that are the int values I specified.

But I want to do that in straight assembly - not C.

The build output (would show the tool chain I imagine) is:

**** Build of configuration Debug for project 00.static.global.const.array.of.ints ****

/opt/ti/ccsv8/utils/bin/gmake -k -j 2 all -O 

Building file: "../main.c"
Invoking: ARM Compiler
"/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me --include_path="/opt/ti/ccsv8/ccs_base/arm/include" --include_path="/opt/ti/ccsv8/ccs_base/arm/include/CMSIS" --include_path="/home/devchu/Development/ti.robotics/tirslk_maze_1_00_00/00.static.global.const.array.of.ints" --include_path="/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/include" --advice:power=all --define=__MSP432P401R__ --define=ccs -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi --preproc_with_compile --preproc_dependency="main.d_raw"  "../main.c"
"../main.c", line 3: warning #179-D: variable "somearr" was declared but never referenced
Finished building: "../main.c"

Building target: "00.static.global.const.array.of.ints.out"
Invoking: ARM Linker
"/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/bin/armcl" -mv7M4 --code_state=16 --float_support=FPv4SPD16 -me --advice:power=all --define=__MSP432P401R__ --define=ccs -g --gcc --diag_warning=225 --diag_wrap=off --display_error_number --abi=eabi -z -m"00.static.global.const.array.of.ints.map" --heap_size=1024 --stack_size=512 -i"/opt/ti/ccsv8/ccs_base/arm/include" -i"/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/lib" -i"/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/include" --reread_libs --diag_wrap=off --display_error_number --warn_sections --xml_link_info="00.static.global.const.array.of.ints_linkInfo.xml" --rom_model -o "00.static.global.const.array.of.ints.out" "./main.obj" "./startup_msp432p401r_ccs.obj" "./system_msp432p401r.obj" "../msp432p401r.cmd"  -llibc.a 
<Linking>
remark #10371-D: (ULP 1.1) Detected no uses of low power mode state changing instructions
remark #10372-D: (ULP 4.1) Detected uninitialized Port 1 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 2 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 3 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 4 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 5 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 6 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 7 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 8 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 9 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
remark #10372-D: (ULP 4.1) Detected uninitialized Port 10 in this project. Recommend initializing all unused ports to eliminate wasted current consumption on unused pins.
Finished building target: "00.static.global.const.array.of.ints.out"

Building files: "00.static.global.const.array.of.ints.out"
Invoking: ARM Hex Utility
"/opt/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.2.LTS/bin/armhex" --memwidth=8 --romwidth=8 -o "00.static.global.const.array.of.ints.hex"  "00.static.global.const.array.of.ints.out" 
Translating to Extended Tektronix format...
   "00.static.global.const.array.of.ints.out" .intvecs ==> .intvecs
   "00.static.global.const.array.of.ints.out" .text ==> .text
   "00.static.global.const.array.of.ints.out" .cinit ==> .cinit
Finished building: "00.static.global.const.array.of.ints.out"


**** Build Finished ****
ecorrales
  • 137
  • 11
  • 1
    It's not clear what/where your **exact** problem is... Is it accessing the Flash memory itself?, or you've never declared constants in Assembly before? – VC.One Oct 17 '18 at 13:19
  • Try something [from research](https://www.google.co.uk/search?safe=strict&ei=PzfHW47nBOvWgAa046DICg&q=assembly+access+flash+memory+-usb) while you wait for someone to answer. On this forum we only help you fix your code but you must [show some code](https://stackoverflow.com/posts/52855579/edit) that is not working. – VC.One Oct 17 '18 at 13:24
  • an array is a high level language concept not an assembly language concept although there may be some assembly languages that pretend. basically you want to declare some data, so that is very assembler specific, usually something like .word or DW or some such thing. One way to figure it out is have the compiler do it for you, do it in C then compile and examine the assembly output of the compiler then steal from that, as the compiler knows the assembly language for the toolchain. – old_timer Oct 17 '18 at 14:12
  • It's for ARM (MSP432). I have used ".set" , ".equ", and ".field" assembler directives. But I want to declare certain values contiguously in Flash memory, then access them from the code. I have accessed values before, example: using the ".field" directive, loaded into a register. But that's not what I'm asking. I want to be able to specify the flash address(es) where these values would reside. Yes, my next step was to do it in C and the view the assembly, but not sure I will be any further ahead in my learning by doing that. – ecorrales Oct 17 '18 at 16:38
  • i updated initial post with new info – ecorrales Oct 18 '18 at 00:28
  • Look at the compiler's asm output from the C source that does what you want, and use that. `gcc -O3 -S` [How to remove "noise" from GCC/clang assembly output?](https://stackoverflow.com/q/38552116). – Peter Cordes Oct 18 '18 at 01:59

2 Answers2

1

In C const int somearr[] = { 1,2,3,4,5,6,7}; places the data in the .rodata segment.

To archive the same you need to place your table in this section

I do not know the code composer but gnu assembler has the .section directive

0

One way to do this, worked for me with an STM32 Nucleo-64 (Nucleo-F303RE). To keep example simple, I ran the code within the reset handler.

.syntax unified
.cpu cortex-m4

.fpu vfpv4

.thumb

.global vtable
.global reset_handler
.type vtable, %object
vtable:
    .word _estack
    .word reset_handler
.size vtable, .-vtable

/***********************************************************
* 'Array' declaration / initialization begins here
***********************************************************/
.type myarray, %object
myarray:
    .word   0x11111111
    .word   0x22222222
    .word   0x33333333
.size myarray, .-myarray
/***********************************************************
* 'Array' declaration / initialization ends here
***********************************************************/

.equ    myarraysize, 5  //the number of 'elements' in the 'array'.


.type reset_handler, %function
reset_handler:
  LDR  r0, =_estack
  MOV  sp, r0

    /******************************************************************
    *  START - code example using array
    /*****************************************************************/

    LDR  R1,=myarray  // this loads the location value itself (the 1st address),

    MOV  R2,#0        // R2 will keep a count to make sure we don't walk off
                      // end of array.

    LDR  R3,=myarrsize // R3 will be the equivalent of 'myarrsize'.

                       // R0 will hold our data (pretends we're using data).

main_loop:
    LDR R0,[R1]        // Load the data pointed to by R1 ('myarray') into R0.
    CMP R2,R3          // Are we at limit of array?
    BEQ main_loop      // If we are, we're done, so we'll just loop forever.
    ADD R2,#1          // Not done, keep going, keep count.
    ADD R1,#4          // Add 4 to register R1, so it points correctly to next
                       // address..
    B    main_loop     // Loop back.     

    /******************************************************************
    *  END - code example using array
    /*****************************************************************/


.size reset_handler, .-reset_handler
ecorrales
  • 137
  • 11