0

我在为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).

我的代码由主例程中的两个独立部分组成:

  1. 等待一个字节通过 UART 到达,在一个时间窗口内收集两个字节,然后对其进行解码并执行一些操作
  2. 等待按钮被按下,等待一段时间然后解码按下的按钮并执行相应的操作(使用 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 操作是否可行?

4

0 回答 0