Cortex M0 - Issue with invalid assembly generation

Asked by LukeL99

Hey everyone,

I'm having an issue that I really cannot figure out for the life of me. I'm trying to port the ST VL53L0x API to an nRF51422_QFAC (the nRF DK). I'm calling the VL53L0X_DataInit function in vl53l0x_api.c, which calls VL53L0X_WrByte function, which is where I'm having my problem. Here is the source code:

 VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data){
  VL53L0X_Error Status = VL53L0X_ERROR_NONE;
  int32_t status_int;
 uint8_t deviceAddress;

 deviceAddress = Dev->I2cDevAddr;

 status_int = VL53L0X_write_byte(deviceAddress, index, data);

 if (status_int != 0)
  Status = VL53L0X_ERROR_CONTROL_INTERFACE;

    return Status;
}

The problem (I think) is that my generated assembly tries to load 0x15C from r3 in an ldrb instruction. Here is the generated assembly from the above method:

                               VL53L0X_WrByte:
0001ee70: VL53L0X_WrByte+0 movs r3, #174 ; 0xae
146 VL53L0X_Error VL53L0X_WrByte(VL53L0X_DEV Dev, uint8_t index, uint8_t data){
0001ee72: VL53L0X_WrByte+2 push {r4, lr}
151 deviceAddress = Dev->I2cDevAddr;
0001ee74: VL53L0X_WrByte+4 lsls r3, r3, #1
153 status_int = VL53L0X_write_byte(deviceAddress, index, data);
0001ee76: VL53L0X_WrByte+6 ldrb r0, [r0, r3]
0001ee78: VL53L0X_WrByte+8 bl 0x1ed14 <VL53L0X_write_byte>
147 VL53L0X_Error Status = VL53L0X_ERROR_NONE;
0001ee7c: VL53L0X_WrByte+12 movs r3, #0
155 if (status_int != 0)
0001ee7e: VL53L0X_WrByte+14 cmp r0, #0
0001ee80: VL53L0X_WrByte+16 bne.n 0x1ee86 <VL53L0X_WrByte+22>
159 }
0001ee82: VL53L0X_WrByte+18 movs r0, r3
0001ee84: VL53L0X_WrByte+20 pop {r4, pc}
156 Status = VL53L0X_ERROR_CONTROL_INTERFACE;
0001ee86: VL53L0X_WrByte+22 subs r3, #20
0001ee88: VL53L0X_WrByte+24 b.n 0x1ee82 <VL53L0X_WrByte+18>
0001ee8a: nop ; (mov r8, r8)
166 deviceAddress = Dev->I2cDevAddr;

It happens at 0x0001ee76. As you can see, r3 is 174, then it's left shifted so it becomes 348. Then it's trying to offset a memory address with a byte, but 348 is too large.

Output of my GCC version

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]
Copyright (C) 2015 Free Software Foundation, Inc.

Am I on the right track here? What is the general thought process behind the optimizations that created this assembly? Should I file a bug on this? Are there any other details I should include?

Thanks in advance.

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
LukeL99
Solved:
Last query:
Last reply:
Revision history for this message
LukeL99 (lukel99) said :
#1

I realize that this is a little hard to read, so I've put the C code and assembly on pastebin:

C code
http://pastebin.com/HDKG0ffD

Assembly with debug info
http://pastebin.com/6r7fA227

Revision history for this message
Andre Vieira (andre-simoesdiasvieira) said :
#2

Hi LukeL99,

Could you post the command line used to compile your code? Also a preprocessed reduced test would be useful. The C-code you posted will not compile on its own (missing types and so on).

Cheers,
Andre

Revision history for this message
Thomas Preud'homme (robotux) said :
#3

Hi Luke,

What is the problem you are having exactly? I see nothing wrong with that ldrb: it loads from a base address (in r0) + an offset (in r3) and loads only a byte at the resulting address. The offset in r3 does not have to fit in one byte.

So, to recap:
1) What is the problem you are having? (and what makes you think the ldrb is the source of the mistake)?
2) we need command line option and preprocessed code (See the .i file created by option -save-temps) to be able to reproduce

Best regards.

Revision history for this message
LukeL99 (lukel99) said :
#4

Hey guys,

This issue was on my end - I was looking at the documentation for LDRB (immediate) and it states that the immediate value has to be between 0 and 30. My issue was that I was using eclipse as my debugger and I was stepping through C lines, and not assembly instructions. It actually happened because my TWI interface wasn't configured correctly.

Thanks for your help and all the hard work you do!

-Luke