Driver for MK22FN512xx I2C0 peripheral

replace/13c0b3b5c6b87756fca8a129930567833673b5ef
Silvano Seva 2020-12-28 12:43:27 +01:00
rodzic 5581276ec5
commit 56d56e901f
3 zmienionych plików z 178 dodań i 0 usunięć

Wyświetl plik

@ -122,6 +122,7 @@ mk22fn512_src = ['platform/mcu/MK22FN512xxx12/boot/startup.c',
'platform/mcu/MK22FN512xxx12/drivers/gpio.c',
'platform/mcu/MK22FN512xxx12/drivers/delays.c',
'platform/mcu/MK22FN512xxx12/drivers/rtc.c',
'platform/mcu/MK22FN512xxx12/drivers/I2C0.c',
'platform/mcu/MK22FN512xxx12/drivers/usb/usb_device_cdc_acm.c',
'platform/mcu/MK22FN512xxx12/drivers/usb/usb_device_ch9.c',
'platform/mcu/MK22FN512xxx12/drivers/usb/usb_device_dci.c',

Wyświetl plik

@ -0,0 +1,112 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include "I2C0.h"
#include <MK22F51212.h>
void i2c0_init()
{
SIM->SCGC4 |= SIM_SCGC4_I2C0(1);
I2C0->A1 = 0; /* Module address when in slave mode */
I2C0->F = 0x2C; /* Divide bus clock by 576 */
I2C0->C1 |= I2C_C1_IICEN(1); /* Enable I2C module */
}
void i2c0_terminate()
{
while(I2C0->S & I2C_S_BUSY(1)) ; /* Wait for bus free */
I2C0->C1 &= ~I2C_C1_IICEN(1);
SIM->SCGC4 &= ~SIM_SCGC4_I2C0(1);
}
void i2c0_write(uint8_t addr, void* buf, size_t len, bool sendStop)
{
I2C0->C1 |= I2C_C1_TX_MASK /* Transmit data */
| I2C_C1_MST_MASK; /* Master mode */
I2C0->D = addr & 0xFE;
for(size_t i = 0; i < len; i++)
{
while((I2C0->S & I2C_S_IICIF_MASK) == 0) ; /* IICIF set on tx completion */
I2C0->S |= I2C_S_IICIF_MASK; /* Clear IICIF flag */
I2C0->D = ((char *) buf)[i];
}
while((I2C0->S & I2C_S_IICIF_MASK) == 0) ; /* Wait for last byte */
I2C0->S |= I2C_S_IICIF_MASK;
if(sendStop)
{
I2C0->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TX_MASK);
while(I2C0->S & I2C_S_BUSY_MASK) ;
}
}
void i2c0_read(uint8_t addr, void* buf, size_t len)
{
/* In case a stop was not sent, send a repeated start instead of a start. */
if(I2C0->C1 & I2C_C1_MST_MASK)
{
I2C0->C1 |= I2C_C1_RSTA_MASK
| I2C_C1_TX_MASK;
}
else
{
I2C0->C1 |= I2C_C1_TX_MASK
| I2C_C1_MST_MASK;
}
I2C0->D = addr | 0x01;
while((I2C0->S & I2C_S_IICIF_MASK) == 0) ; /* Wait end of address transfer */
I2C0->S |= I2C_S_IICIF_MASK; /* Clear IICIF flag */
I2C0->C1 &= ~I2C_C1_TX_MASK; /* Configure peripheral for data reception */
(void) I2C0->D; /* Flush RX with a dummy read, also clears TCF */
for(size_t i = 0; i < len - 1; i++)
{
while((I2C0->S & I2C_S_IICIF_MASK) == 0) ;
I2C0->S |= I2C_S_IICIF_MASK;
((char *) buf)[i] = I2C0->D;
}
/* Send NACK on last byte read */
I2C0->C1 |= I2C_C1_TXAK_MASK;
while((I2C0->S & I2C_S_IICIF_MASK) == 0) ;
I2C0->S |= I2C_S_IICIF_MASK;
/* All bytes received, send stop */
I2C0->C1 &= ~(I2C_C1_MST_MASK | I2C_C1_TXAK_MASK);
/* Read last byte */
((char *) buf)[len - 1] = I2C0->D;
/* Wait until stop has been sent */
while(I2C0->S & I2C_S_BUSY_MASK) ;
}
bool i2c0_busy()
{
return (I2C0->S & I2C_S_BUSY_MASK);
}

Wyświetl plik

@ -0,0 +1,65 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef I2C0_H
#define I2C0_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
/**
* Initialise I2C peripheral with a bus clock frequency of ~100kHz.
* NOTE: this driver does not configure the I2C GPIOs, which have to be put in
* alternate open drain mode by application code.
*/
void i2c0_init();
/**
* Shut down I2C peripheral.
* NOTE: is left to application code to change the operating mode of the I2C
* GPIOs
*/
void i2c0_terminate();
/**
* Write data to an I2C peripheral.
* @param addr: address of target peripheral.
* @param buf: pointer to buffer containing data to be sent.
* @param len: number of bytes to be sent.
* @param sendStop: set to true to generate a stop condition on transfer end.
*/
void i2c0_write(uint8_t addr, void *buf, size_t len, bool sendStop);
/**
* Read data from an I2C peripheral.
* @param addr: address of target peripheral.
* @param buf: pointer to a buffer in which received data are written.
* @param len: number of bytes to be transferred.
*/
void i2c0_read(uint8_t addr, void *buf, size_t len);
/**
* Check if I2C bus is already in use.
* @return true if bus is busy.
*/
bool i2c0_busy();
#endif /* I2C0_H */