user1397215
user1397215

Reputation: 321

Map interrupt handlers for SAM L10 device

I have been attempting to set up the I2C on a system which uses the SAM L10 MCU. I have been able to build my project on MPLAB X as a standalone project without having to use MPLAB Harmony v3 code configurator. My problem is I can't seem to get the interrupt handlers to be mapped correctly.

Here are the references I am using: https://github.com/Microchip-MPLAB-Harmony/csp_apps_sam_l10_l11/tree/master/apps/sercom/i2c/master/i2c_eeprom and https://microchipdeveloper.com/32arm:samd21-code-gcc-nvic-example

In both cases, there seems to be a table which assigns function pointers for the interrupt handlers, called exception_table. I do not know the correct way to incorporate this in my code, in fact, I don't understand how this code actually gets executed as it is simply assigning the function pointers.

Here is what I have for my code:

init.c

#include <xc.h>
#include "peripheral/clock/plib_clock.h"
#include "peripheral/nvic/plib_nvic.h"
#include "peripheral/sercom/plib_sercom0_i2c_master.h"

#pragma config NVMCTRL_NSULCK = 0x7
#pragma config BOD33_LEVEL = 0x6
#pragma config BOD33_DIS = CLEAR
#pragma config BOD33_ACTION = 0x1
#pragma config WDT_RUNSTDBY = CLEAR
#pragma config WDT_ENABLE = SET
#pragma config WDT_ALWAYSON = CLEAR
#pragma config WDT_PER = 0x9
#pragma config WDT_WINDOW = 0xB
#pragma config WDT_EWOFFSET = 0xB
#pragma config WDT_WEN = CLEAR
#pragma config BOD33_HYST = CLEAR


void port_init (void)
{
    /* Configure SERCOM0 I2C on PA22 and PA23, Peripheral function C */
    PORT_REGS->GROUP[0].PORT_PINCFG[22] = 0x1;
    PORT_REGS->GROUP[0].PORT_PINCFG[23] = 0x1;
    PORT_REGS->GROUP[0].PORT_PMUX[11] = 0x22;

    
    /* Configure PA25 as an output driven high */
    PORT_REGS->GROUP[0].PORT_DIR = 0x02000000;
    PORT_REGS->GROUP[0].PORT_OUT = 0x02000000;
    PORT_REGS->GROUP[0].PORT_PINCFG[27] = 0x0;
}

void sys_initialise (void)
{
    CLOCK_Initialize ();
    port_init ();
    
    
    SERCOM0_I2C_Initialize ();
    NVIC_Initialize ();   
  
}

main.c

#include <xc.h>
#include "init.h"
#include "peripheral/sercom/plib_sercom0_i2c_master.h"

void main (void)
{
    sys_initialise ();

    uint8_t reg[1];
    reg[0] = 0xD0;    

    SERCOM0_I2C_Write (0x76, &reg[0], 2);    
}

I used the GPIO for my debugging. I thought setting up the NVIC would be enough but it only enables the interrupt themselves, the interrupt handler is still not mapped. I can see it because from my debugging the handler never gets called when I try to send something over I2C. I can also see the I2C work correctly for sending the first part of the transaction, which is the device address up to the ACK bit. From this point on, I can see on the scope that the clock is held low but the SDA comes back to high. I believe it is because the interrupt handler SERCOM0_I2C_InterruptHandler from https://github.com/Microchip-MPLAB-Harmony/csp_apps_sam_l10_l11/blob/master/apps/sercom/i2c/master/i2c_eeprom/firmware/src/config/sam_l10_xpro/peripheral/sercom/i2c_master/plib_sercom0_i2c_master.c does not get called, as this is responsible for sending the rest of the data.

Upvotes: 0

Views: 255

Answers (1)

user1397215
user1397215

Reputation: 321

I found the answer to this in the user guide for the xc32 compiler which can be accessed here: https://ww1.microchip.com/downloads/en/DeviceDoc/XC32_PICC_UG_DS50002895A.pdf

I was missing the call to NVIC_SetVector() - section 14.3 shows how to associate the interrupt handler with an exception.

Upvotes: 0

Related Questions