我在为Mico8 处理器编写 ac 程序时收到以下错误消息,它只允许相对跳转(第 14 页):
lm8-elf-gcc -mcall-stack-size=16 -mcmodel=medium -T ../platform1/Release/linker.ld -oHTMDAC_Single_Channel.elf Release/../Mico8Interrupts.o Release/../htm_dac_utils.o Release/../main.o Release/crt0.o ./Release/libplatform1.a -lgcc -nostdlib -Wl,--gc-sections
Release/crt0.o:(.vectors+0x1): relocation truncated to fit: R_LM8_12_PCREL against symbol `__irq_save_restore2' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_irq_save_restore.o)
Release/../Mico8Interrupts.o: In function `MicoISRHandler':
Mico8Interrupts.c:(.text.MicoISRHandler+0xd): relocation truncated to fit: R_LM8_12_PCREL against symbol `__prologue_save_r25' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_prologue.o)
makefile:125: recipe for target `HTMDAC_Single_Channel.elf' failed
Mico8Interrupts.c:(.text.MicoISRHandler+0xe2): relocation truncated to fit: R_LM8_12_PCREL against symbol `__epilogue_restore_r25' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_epilogue.o)
Release/../htm_dac_utils.o: In function `set_leds':
htm_dac_utils.c:(.text.set_leds+0xd): relocation truncated to fit: R_LM8_12_PCREL against symbol `__prologue_save_r17' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_prologue.o)
htm_dac_utils.c:(.text.set_leds+0x9a): relocation truncated to fit: R_LM8_12_PCREL against symbol `__epilogue_restore_r17' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_epilogue.o)
Release/../main.o: In function `MicoTimerISR':
main.c:(.text.MicoTimerISR+0xd): relocation truncated to fit: R_LM8_12_PCREL against symbol `__prologue_save_r10' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_prologue.o)
main.c:(.text.MicoTimerISR+0x7c): relocation truncated to fit: R_LM8_12_PCREL against symbol `__epilogue_restore_r10' defined in .text section in /cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_epilogue.o)
/cygdrive/C/lscc/diamond/3.12/micosystem/gtools/lm8/bin/../lib/gcc/lm8-elf/4.4.3/libgcc.a(_irq_save_restore.o): In function `__irq_save_restore2':
(.text+0x91): relocation truncated to fit: R_LM8_12_PCREL against symbol `__IRQ' defined in .text.(int0_t) section in Release/../Mico8Interrupts.o
我的解释relocation truncated to fit: R_LM8_12_PCREL
是链接器试图将真实的跳转地址放入操作码中,该地址大于允许的signed offset (+2047/-2048)
.
我的代码由主例程中的两个独立部分组成:
- 等待一个字节通过 UART 到达,在一个时间窗口内收集两个字节,然后对其进行解码并执行一些操作
- 等待按钮被按下,等待一段时间然后解码按下的按钮并执行相应的操作(使用 FSM)
编码:
/*
* main.c
*
* Created on: Nov 16, 2021
* Author: pekomi47
*/
#include "DDStructs.h"
#include "MicoUtils.h"
#include "MicoGPIO.h"
#include "MicoTimer.h"
#include "MicoUart.h"
#include "system_conf.h"
#include "MicoInterrupts.h"
#include "htm_dac_utils.h"
#define n_channels 4
#define IRQ_LEVEL_TIMER_UART 1
#define IRQ_LEVEL_TIMER_BUTTONS 2
void MicoTimerISR (MicoTimerCtx_t *ctx);
void MicoGPIOISR (MicoGPIOCtx_t *ctx);
volatile char timer_overflow_uart = 0x01;
volatile char timer_overflow_button = 0x00;
volatile char button_pressed_IRQ = 0x00;
unsigned char freezed_button_values, new_button_values = 0x00;
unsigned char long_press = 0x00;
unsigned int button_sm = S_IDLE;
char uart_bytes[2];
unsigned char uart_byte_pointer = 0x00;
unsigned char uart_command = 0x00;
unsigned int uart_value = 0x00;
MicoGPIOCtx_t *leds = &gpio_LED;
MicoUartCtx_t *uart = &uart_core_uart;
MicoTimerCtx_t* timer_uart = &timer_input_uart;
MicoGPIOCtx_t * buttons = &gpio_buttons;
MicoTimerCtx_t * timer_button = &timer_input_buttons;
int main(void){
MICO_GPIO_WRITE_IRQ_MASK_BYTE0(buttons->base, 0x7F);
struct system_info system = {
.led_enable = 0x01,
.active_channels = 0x00,
.trigger_sensitivity = 0x00
};
set_leds(leds, &system);
while(1){
if(uart->rxDataBytes > 0){
if(timer_overflow_uart == 0x01){
timer_overflow_uart = 0;
uart_byte_pointer = 0;
MicoTimerStop(timer_uart);
MicoTimerStart(timer_uart, 0, MILLISECONDS_TO_TICKS(100));
}
MicoUart_getC(uart , &uart_bytes[uart_byte_pointer++]);
if(uart_byte_pointer == 0x02){
timer_overflow_uart = 1;
uart_command = (uart_bytes[0] >> 2) & 0x0F;
uart_value = (uart_bytes[0] & 0x03) << 8 | uart_bytes[1];
switch(uart_command){
case ENABLE_LEDS:
system.led_enable = max_min(uart_value, 0, 1);
break;
case SET_TRIGGER_SENSITIVITY:
system.trigger_sensitivity = max_min(uart_value, 0, 1);
MICO_TRIGGER_CONTROLLER_SENSITIVITY(system.trigger_sensitivity);
break;
default:
if(system.trigger_sensitivity){
switch(uart_command){
case SERIAL_TRIGGER:
MICO_TRIGGER_CONTROLLER_TRIGGER(uart_value & 0x0F);
MICO_TRIGGER_CONTROLLER_TRIGGER(0);
break;
default:
//ERROR
break;
}
}
else{
switch(uart_command){
case SET_ACTIVE_CHANNEL:
if (uart_value < n_channels || uart_value == 1023){
system.active_channels = uart_value;
}
break;
case SET_MANUAL_VOLTAGE:
MICO_CHANNEL_REG_1_WRITE((uart_value >> 8) & 0x3);
MICO_CHANNEL_REG_2_WRITE(uart_value & 0xFF);
MICO_CHANNEL_MANUAL_VOLTAGE(0x01);
break;
case SET_TRIGGER_SOURCE:;
char ts = max_min(uart_value, 0, 1);
MICO_CHANNEL_TRIGGER_SOURCE(ts);
break;
case SET_TRIGGER_ID:;
char ch_id = max_min(uart_value, 0, 3);
MICO_CHANNEL_ID(ch_id);
break;
case SET_END_OF_SEQUENCE_MODE:;
char eosm = max_min(uart_value, 0, 1);
MICO_CHANNEL_END_OF_SEQUENCE_MODE(eosm);
break;
case SAVE_VOLTAGE_VALUE:
MICO_CHANNEL_REG_1_WRITE((uart_value >> 8) & 0x3);
MICO_CHANNEL_REG_2_WRITE(uart_value & 0xFF);
MICO_CHANNEL_WRITE_VOLTAGE(0x01);
break;
case RESET_MEMORY:
MICO_CHANNEL_MEMORY_RESET(0x01);
break;
default:
//ERROR
break;
}
}
break;
}
set_leds(leds, &system);
}
}
else{
unsigned int timer_time_ms;
switch(button_sm){
case(S_IDLE):
if(button_pressed_IRQ == 0x01){
button_pressed_IRQ = 0x00;
timer_time_ms = 300;
freezed_button_values = 0x00;
button_sm = S_START_TIMER;
}
break;
case(S_START_TIMER):
timer_overflow_button == 0x00;
MicoTimerStop(timer_button);
MicoTimerStart(timer_button, 0, MILLISECONDS_TO_TICKS(timer_time_ms));
button_sm = S_WAIT_FOR_TIMER;
break;
case(S_WAIT_FOR_TIMER):
MICO_GPIO_READ_DATA_BYTE0(buttons->base , new_button_values);
if(new_button_values == 0x00){
button_sm = S_IDLE;
}
else if (freezed_button_values == 0x00){
if(timer_overflow_button == 0x01){
freezed_button_values = new_button_values;
long_press = 0x00;
button_sm = S_SELECT_ACTION;
}
}
else if (new_button_values == freezed_button_values){
if(timer_overflow_button == 0x01){
button_sm = S_SELECT_ACTION;
long_press = 0x01;
}
}
else {
button_sm = S_INPUT_BLOCK;
}
break;
case(S_SELECT_ACTION):
switch(freezed_button_values){
case MANUAL_VOLTAGE_BUTTON_PLUS_MASK:
// increment manual voltage
// read in current manual voltage of selected channel
// write new manual voltage of selected channel
timer_time_ms = 300;
button_sm = S_START_TIMER;
break;
case MANUAL_VOLTAGE_BUTTON_MINUS_MASK:
// decrement manual voltage
// read in current manual voltage of selected channel
// write new manual voltage of selected channel
timer_time_ms = 300;
button_sm = S_START_TIMER;
break;
case CHANNEL_SELECT_BUTTON_PLUS_MASK:
system.active_channels = (system.active_channels + 1) % n_channels;
button_sm = S_INPUT_BLOCK;
break;
default:
button_sm = S_INPUT_BLOCK;
break;
}
break;
case S_INPUT_BLOCK:
if(new_button_values == 0x00){
button_sm = S_IDLE;
}
break;
}
}
}
}
void MicoTimerISR (MicoTimerCtx_t *ctx)
{
size_t il = ctx->intrLevel;
switch(il){
case IRQ_LEVEL_TIMER_UART:
timer_overflow_uart = 0x01;
break;
case IRQ_LEVEL_TIMER_BUTTONS:
button_pressed_IRQ = 0x01;
break;
}
size_t timer_address = (size_t) ctx->base;
//Clear Pending Interrupt
MICO_TIMER_WRITE_STATUS(timer_address, 0x0);
}
void MicoGPIOISR (MicoGPIOCtx_t *ctx){
button_pressed_IRQ = 0x01;
MICO_GPIO_WRITE_EDGE_CAPTURE_BYTE0(ctx->base ,0x00);
}
是否有一种编码风格可以绕过大型程序中只能使用相对跳转的限制。使用标签和 goto 操作是否可行?