Неожиданное поведение при копировании указателей (встроенный XC8) - PullRequest
0 голосов
/ 13 июля 2020

Я создал обработчик (структуру), чтобы иметь интерфейс для EUSART, который не зависит от фактического номера EUSART.

Вот код API шины:

// Type definitions    
typedef uint8_t (*EUSART_Read_Func)(void);
typedef uint8_t (*EUSART_LastStatus_Func)(void);
typedef uint8_t (*EUSART_get_RXCount)(void);

typedef struct {
        EUSART_Read_Func pxRead;
        EUSART_LastStatus_Func pxLastStatus;
        EUSART_get_RXCount pxRXCount;
        uint8_t ucFramePointer;
        uint8_t ucChecksum;
        volatile uint8_t *pxPingBuffer;
        volatile uint8_t *pxPongBuffer;
        volatile uint8_t *pxCurrentFrameBuffer;
        uHMPBusRXStatus uRXStatus;
}xHMPBusHandler;

// Global variables
volatile uint8_t ucHMPBus1FrameBufferPing[BUFFSIZE];
volatile uint8_t ucHMPBus1FrameBufferPong[BUFFSIZE];
    
volatile xHMPBusHandler xHMPBus1Handler;

//APIs
void vHMPBusInit (void) {
    // Use EUSART1
    xHMPBus1Handler.pxLastStatus = EUSART1_get_last_status;
    xHMPBus1Handler.pxRXCount = EUSART1_get_RXCount;
    xHMPBus1Handler.pxRead = EUSART1_Read;

    // Initialize Bus 1 handler
    xHMPBus1Handler.ucChecksum = 0;
    xHMPBus1Handler.uRXStatus.usStatus = CLEAR;
    xHMPBus1Handler.ucFramePointer = 0;
    xHMPBus1Handler.pxPingBuffer = ucHMPBus1FrameBufferPing;
    xHMPBus1Handler.pxPongBuffer = ucHMPBus1FrameBufferPong;
    xHMPBus1Handler.pxCurrentFrameBuffer = xHMPBus1Handler.pxPingBuffer;
}

volatile uint8_t *pxTestPointer;

// Get the data from the EUSART
void vHMPBusGetData( volatile xHMPBusHandler * puBus ) {
    uint8_t ucData;
    eusart1_RXstatus_t xLastStatus;
    uint8_t ucRXCount;
    
    // Get number of byte in the communication buffer
    ucRXCount = puBus->pxRXCount();
    
    // Get all byte currently in the communication buffer
    while (ucRXCount)
    {
        // Read 1 byte from the communication buffer and acquire its status
        ucData = puBus->pxRead();

        // Some code left out of this example

        // Store the received byte in the HMP bus buffer
        if ( puBus->uRXStatus.HMPBufferOverflow ) {
            return;
        } else {
            puBus->pxCurrentFrameBuffer[puBus->ucFramePointer++] = ucData;
        }
   
        // Select buffer
        if (puBus->uRXStatus.PingFull) {
            puBus->pxCurrentFrameBuffer = puBus->pxPingBuffer;
        } else {
            pxTestPointer = puBus->pxPongBuffer;
            puBus->pxCurrentFrameBuffer = ucTest;
        }
        
        // Check if full frame has been received
        if (puBus->ucFramePointer >= FRAMESIZE)
        {
            if (puBus->pxCurrentFrameBuffer == puBus->pxPingBuffer)
                puBus->uRXStatus.PingFull = true;
            else
                puBus->uRXStatus.PongFull = true;
        }
    }
}

Это основной код, вызывающий функции API:

void main(void) {
    // initialize
    vHMPBusInit ();

    // Enable the Global- and Peripheral Interrupts
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    while (1) {
        vHMPBusGetData(&xHMPBus1Handler);
    }
}

Все начинает казаться мне странным в следующих строках кода:

    // Select buffer
    if (puBus->uRXStatus.PingFull) {
        puBus->pxCurrentFrameBuffer = puBus->pxPingBuffer;
   } else {
        // Test to see what happens with indirect copy of pointer
        pxTestPointer = puBus->pxPongBuffer;
        puBus->pxCurrentFrameBuffer = pxTestPointer;

        puBus->pxCurrentFrameBuffer = puBus->pxPongBuffer;
   }

После отладки я заметил что-то странное. Копирование указателя на PingBuffer (на который ссылается puBus) непосредственно в pxCurrentFrameBuffer, привело к неожиданному адресу, хранящемуся в pxCurrentFrameBuffer.

Когда я пытаюсь сделать это косвенно, как проверено в части кода ELSE, используя pxTestPointer, адрес копируется из pxPongBuffer в pxTestPointer и рядом с pxCurrentFrameBuffer, как и ожидалось.

Что мне не хватает?

Любая помощь будет принята с благодарностью.

Gr. Майк

Я также приложил просмотры памяти и листинг дизассемблера

!                pxTestPointer = puBus->pxPongBuffer;
0x13D: MOVF ucCRCHi, W
0x13E: ADDLW 0x9
0x13F: MOVWF FSR1
0x140: CLRF FSR1H
0x141: MOVF INDF1, W
0x142: MOVWF pxTestPointer
0x143: MOVLW 0x1
0x144: MOVWF 0x3F
!                puBus->pxCurrentFrameBuffer = pxTestPointer;
0x145: MOVF ucCRCHi, W
0x146: ADDLW 0xA
0x147: MOVWF FSR1
0x148: CLRF FSR1H
0x149: MOVF pxTestPointer, W
0x14A: MOVWI 0[FSR1]
0x14B: MOVF 0x3F, W
0x14C: MOVWI 1[FSR1]
!                puBus->pxCurrentFrameBuffer = puBus->pxPongBuffer;
0x14D: MOVF ucCRCHi, W
0x14E: ADDLW 0x9
0x14F: MOVWF FSR1
0x150: CLRF FSR1H
0x151: MOVF ucCRCHi, W
0x152: ADDLW 0xA
0x153: MOVWF FSR0
0x154: CLRF FSR0H
0x155: MOVF FSR1, W
0x156: MOVWI 0[FSR0]
0x157: MOVLW 0x1
0x158: MOVWI 1[FSR0]

После инициализации:

After init

After copy using pxTestPointer: After copy using pxTestPointer

After direct copy: После прямой копии

...