Reputation: 321
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, ®[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
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