Merge pull request #235 from elfmimi/numicro-i2c
NUMICRO: add I2C driver
This commit is contained in:
commit
b4815d9105
|
@ -29,3 +29,6 @@ https://github.com/Codetector1374
|
|||
|
||||
Alex Lewontin aka alexclewontin
|
||||
https://github.com/alexclewontin
|
||||
|
||||
Ein Terakawa aka a_p_u_r_o
|
||||
https://github.com/elfmimi
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
ifeq ($(USE_SMART_BUILD),yes)
|
||||
ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
|
||||
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/I2Cv1/hal_i2c_lld.c
|
||||
endif
|
||||
else
|
||||
PLATFORMSRC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/I2Cv1/hal_i2c_lld.c
|
||||
endif
|
||||
|
||||
PLATFORMINC += $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/I2Cv1
|
|
@ -0,0 +1,529 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2019 Ein Terakawa
|
||||
Copyright (C) 2014-2015 Fabio Utzig
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file NUMICRO/hal_i2c_lld.c
|
||||
* @brief NUMICRO I2C subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_I2C || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define I2C_I2CON_STA I2C_I2CON_STA_Msk
|
||||
#define I2C_I2CON_STO I2C_I2CON_STO_Msk
|
||||
#define I2C_I2CON_SI I2C_I2CON_SI_Msk
|
||||
#define I2C_I2CON_AA I2C_I2CON_AA_Msk
|
||||
#define I2C_I2CON_STA_STO_SI_AA (I2C_I2CON_STA|I2C_I2CON_STO|I2C_I2CON_SI|I2C_I2CON_AA)
|
||||
#define I2C_Trigger(i2c, sta, sto, si, ack) ((i2c)->I2CON = (((i2c)->I2CON & ~(I2C_I2CON_STA_STO_SI_AA)) | ((sta)?(I2C_I2CON_STA):0) | ((sto)?(I2C_I2CON_STO):0) | ((si)?(I2C_I2CON_SI):0) | ((ack)?(I2C_I2CON_AA):0)))
|
||||
|
||||
#define I2C_START(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_SI) | I2C_I2CON_STA)
|
||||
#define I2C_STOP(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_SI) | I2C_I2CON_STO)
|
||||
#define I2C_ENABLE(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_ENS1_Msk))
|
||||
#define I2C_DISABLE(i2c) ((i2c)->I2CON = ((i2c)->I2CON & ~I2C_I2CON_ENS1_Msk))
|
||||
#define I2C_EnableInt(i2c) ((i2c)->I2CON = ((i2c)->I2CON | I2C_I2CON_EI_Msk))
|
||||
#define I2C_DisableInt(i2c) ((i2c)->I2CON = ((i2c)->I2CON & ~I2C_I2CON_EI_Msk))
|
||||
#define I2C_ClearTimeoutFlag(i2c) ((i2c)->I2CTOC = ((i2c)->I2CTOC | I2C_I2CTOC_TIF_Msk))
|
||||
#define I2C_GET_STATUS(i2c) ((i2c)->I2CSTATUS)
|
||||
#define I2C_SET_DATA(i2c, u8dat) ((i2c)->I2CDAT = (u8dat))
|
||||
#define I2C_GET_DATA(i2c) ((i2c)->I2CDAT)
|
||||
#define I2C_GET_TIMEOUT_FLAG(i2c) (((i2c)->I2CTOC & I2C_I2CTOC_TIF_Msk)?1:0)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief I2C0 driver identifier.
|
||||
*/
|
||||
#if NUMICRO_I2C_USE_I2C0 || defined(__DOXYGEN__)
|
||||
I2CDriver I2CD0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 driver identifier.
|
||||
*/
|
||||
#if NUMICRO_I2C_USE_I2C1 || defined(__DOXYGEN__)
|
||||
I2CDriver I2CD1;
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static void i2c_config_frequency(I2CDriver *i2cp) {
|
||||
|
||||
uint8_t divisor;
|
||||
|
||||
if (i2cp->config != NULL)
|
||||
divisor = (I2C_PCLK * 10 / (i2cp->config->clock * 4) + 5) / 10 - 1;
|
||||
else
|
||||
divisor = I2C_PCLK / 4 / 100000 - 1;
|
||||
|
||||
i2cp->i2c->I2CLK = divisor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Common IRQ handler.
|
||||
* @note Tries hard to clear all the pending interrupt sources, we don't
|
||||
* want to go through the whole ISR and have another interrupt soon
|
||||
* after.
|
||||
*
|
||||
* @param[in] i2cp pointer to an I2CDriver
|
||||
*/
|
||||
static void serve_interrupt(I2CDriver *i2cp) {
|
||||
|
||||
I2C_TypeDef *i2c = i2cp->i2c;
|
||||
|
||||
if (I2C_GET_TIMEOUT_FLAG(i2c)) {
|
||||
i2cp->errors |= I2C_TIMEOUT;
|
||||
I2C_ClearTimeoutFlag(i2c);
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t status = (uint8_t)I2C_GET_STATUS(i2c);
|
||||
|
||||
if (status == 0x08 || status == 0x10) {
|
||||
if (i2cp->intstate == STATE_STOP) {
|
||||
I2C_DisableInt(i2c);
|
||||
return;
|
||||
}
|
||||
i2cp->is_master = 1;
|
||||
}
|
||||
|
||||
/* check if we're master or slave */
|
||||
if (i2cp->is_master) {
|
||||
/* master */
|
||||
|
||||
if (status == 0x38 || status == 0x68 || status == 0x78 || status == 0xB0) {
|
||||
/* check if we lost arbitration */
|
||||
i2cp->errors |= I2C_ARBITRATION_LOST;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
/* TODO: may need to do more here, reset bus? */
|
||||
/* Perhaps clear MST? */
|
||||
i2cp->is_master = 0;
|
||||
}
|
||||
else if (status == 0x08 || status == 0x10) {
|
||||
uint8_t op = (i2cp->intstate == STATE_SEND) ? 0 : 1;
|
||||
I2C_SET_DATA(i2c, (i2cp->addr << 1) | op);
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
}
|
||||
else if (status == 0x18 || status == 0x28) {
|
||||
/* ACK */
|
||||
if (i2cp->txbuf != NULL && i2cp->txidx < i2cp->txbytes) {
|
||||
/* slave ACK'd and we want to send more */
|
||||
I2C_SET_DATA(i2c, i2cp->txbuf[i2cp->txidx++]);
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
} else {
|
||||
/* slave ACK'd and we are done sending */
|
||||
if (i2cp->rxbuf != NULL && i2cp->rxbytes != 0) {
|
||||
i2cp->intstate = STATE_RECV;
|
||||
I2C_START(i2c); // should we use Repeat-START ?
|
||||
} else {
|
||||
i2cp->intstate = STATE_STOP;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 1, /* SI */ 1, /* Ack */ 0);
|
||||
/* this wakes up the waiting thread at the end of ISR */
|
||||
_i2c_wakeup_isr(i2cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (status == 0x20 || status == 0x30) {
|
||||
/* NAK */
|
||||
i2cp->errors |= I2C_ACK_FAILURE;
|
||||
i2cp->intstate = STATE_STOP;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 1, /* SI */ 1, /* Ack */ 0); // go to Repeated-START state
|
||||
}
|
||||
else if (status == 0x40) {
|
||||
/* ACK to read request */
|
||||
#if 1
|
||||
if (i2cp->rxidx + 1 == i2cp->rxbytes) {
|
||||
/* only one byte to receive */
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
} else {
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (status == 0x50 || status == 0x58) {
|
||||
/* one byte done */
|
||||
if (i2cp->rxbuf == NULL || i2cp->rxidx >= i2cp->rxbytes) {
|
||||
/* this is unexpected. */
|
||||
i2cp->errors |= I2C_OVERRUN; // is this the apropriate error code?
|
||||
i2cp->intstate = STATE_STOP;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 1, /* SI */ 1, /* Ack */ 0);
|
||||
}
|
||||
else {
|
||||
i2cp->rxbuf[i2cp->rxidx++] = I2C_GET_DATA(i2c);
|
||||
if (i2cp->rxidx == i2cp->rxbytes) {
|
||||
/* last byte done */
|
||||
i2cp->intstate = STATE_STOP;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 1, /* SI */ 1, /* Ack */ 0);
|
||||
_i2c_wakeup_isr(i2cp);
|
||||
}
|
||||
else if (i2cp->rxidx + 1 == i2cp->rxbytes) {
|
||||
/* next byte is the last */
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
}
|
||||
else {
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 0, /* SI */ 1, /* Ack */ 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (status == 0x48) {
|
||||
/* NAK to read request */
|
||||
i2cp->errors |= I2C_ACK_FAILURE;
|
||||
i2cp->intstate = STATE_STOP;
|
||||
I2C_Trigger(i2c, /* Start */ 0, /* Stop */ 1, /* SI */ 1, /* Ack */ 0);
|
||||
}
|
||||
else if (status == 0xF8) {
|
||||
/* CAUTION! I2CSTATUS == 0xF8 won't trigger interrupt! */
|
||||
/* everything completed */
|
||||
// i2cp->is_master = 0;
|
||||
// i2cp->intstate = STATE_STOP;
|
||||
}
|
||||
else {
|
||||
/* need anything else? */
|
||||
}
|
||||
} else {
|
||||
/* slave */
|
||||
|
||||
/* Not implemented yet */
|
||||
}
|
||||
|
||||
/* Reset other interrupt sources */
|
||||
|
||||
/* Reset interrupt flag */
|
||||
|
||||
if (i2cp->errors != I2C_NO_ERROR)
|
||||
_i2c_wakeup_error_isr(i2cp);
|
||||
else if (i2cp->intstate == STATE_STOP && i2cp->is_master == 0)
|
||||
_i2c_wakeup_isr(i2cp);
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C0 || defined(__DOXYGEN__)
|
||||
|
||||
OSAL_IRQ_HANDLER(NUMICRO_I2C0_IRQ_VECTOR) {
|
||||
|
||||
OSAL_IRQ_PROLOGUE();
|
||||
serve_interrupt(&I2CD0);
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1 || defined(__DOXYGEN__)
|
||||
|
||||
OSAL_IRQ_HANDLER(NUMICRO_I2C1_IRQ_VECTOR) {
|
||||
|
||||
OSAL_IRQ_PROLOGUE();
|
||||
serve_interrupt(&I2CD1);
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level I2C driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void i2c_lld_init(void) {
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C0
|
||||
i2cObjectInit(&I2CD0);
|
||||
I2CD0.thread = NULL;
|
||||
I2CD0.i2c = I2C0;
|
||||
I2CD0.is_master = 0;
|
||||
/* Select I2C0 Pins PF.2 and PF.3 as I2C0_SDA and I2C0_SCL*/
|
||||
#ifdef NUC123xxxANx
|
||||
SYS->GPF_MFP |= 0x000C;
|
||||
SYS->ALT_MFP1 = (SYS->ALT_MFP1 & 0xF0FFFFFF) | 0x0A000000;
|
||||
#endif
|
||||
#ifdef NUC123xxxAEx
|
||||
SYS->GPF_MFPL = (SYS->GPF_MFPL & 0xFFFF00FF) | 0x00002200;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1
|
||||
i2cObjectInit(&I2CD1);
|
||||
I2CD1.thread = NULL;
|
||||
I2CD1.i2c = I2C1;
|
||||
I2CD1.is_master = 0;
|
||||
/* Select I2C1 Pins PA.10 and PA.11 as I2C1_SDA and I2C1_SCL */
|
||||
#ifdef NUC123xxxANx
|
||||
SYS->GPA_MFP |= 0x0C00;
|
||||
SYS->ALT_MFP = (SYS->ALT_MFP & 0xFFFFE7FF) | 0x00000000;
|
||||
#endif
|
||||
#ifdef NUC123xxxAEx
|
||||
SYS->GPA_MFPH = (SYS->GPA_MFPH & 0xFFFF00FF) | 0x00001100;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the I2C peripheral.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void i2c_lld_start(I2CDriver *i2cp) {
|
||||
/* We are already covered with osalSysLock() which is same as
|
||||
* __disable_irq(). We don't need farther protection by osalSysDisable().
|
||||
*/
|
||||
|
||||
if (i2cp->state == I2C_STOP) {
|
||||
|
||||
/* TODO:
|
||||
* The PORT must be enabled somewhere. The PIN multiplexer
|
||||
* will map the I2C functionality to some PORT which must
|
||||
* then be enabled. The easier way is enabling all PORTs at
|
||||
* startup, which is currently being done in __early_init.
|
||||
*/
|
||||
#if NUMICRO_I2C_USE_I2C0
|
||||
if (&I2CD0 == i2cp) {
|
||||
/* Eable I2C0 Module Clock */
|
||||
CLK->APBCLK |= CLK_APBCLK_I2C0_EN_Msk;
|
||||
/* Reset I2C0 Module */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_I2C0_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2C0_RST_Msk;
|
||||
nvicEnableVector(NUMICRO_I2C0_IRQ_NUMBER, NUMICRO_I2C_I2C0_PRIORITY);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1
|
||||
if (&I2CD1 == i2cp) {
|
||||
/* Eable I2C1 Module Clock */
|
||||
CLK->APBCLK |= CLK_APBCLK_I2C1_EN_Msk;
|
||||
/* Reset I2C1 Module */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_I2C1_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2C1_RST_Msk;
|
||||
nvicEnableVector(NUMICRO_I2C1_IRQ_NUMBER, NUMICRO_I2C_I2C1_PRIORITY);
|
||||
}
|
||||
#endif
|
||||
|
||||
// uint32_t bus_clock = i2cp->config ? i2cp->config->clock : 100000;
|
||||
// I2C_Open(i2cp->i2c, bus_clock);
|
||||
i2c_config_frequency(i2cp);
|
||||
/* Enable I2Cx Module */
|
||||
I2C_ENABLE(i2cp->i2c);
|
||||
/* Enable Interrupt for I2Cx */
|
||||
I2C_EnableInt(i2cp->i2c);
|
||||
i2cp->intstate = STATE_STOP; // internal state
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the I2C peripheral.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void i2c_lld_stop(I2CDriver *i2cp) {
|
||||
/* We are already covered with osalSysLock() which is same as
|
||||
* __disable_irq(). We don't need farther protection by osalSysDisable().
|
||||
*/
|
||||
|
||||
if (i2cp->state != I2C_STOP) {
|
||||
/* Disable Interrupt for I2Cx */
|
||||
I2C_DisableInt(i2cp->i2c);
|
||||
#if NUMICRO_I2C_USE_I2C0
|
||||
if (&I2CD0 == i2cp) {
|
||||
/* Reset I2C0 Module */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_I2C0_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2C0_RST_Msk;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1
|
||||
if (&I2CD1 == i2cp) {
|
||||
/* Reset I2C1 Module */
|
||||
SYS->IPRSTC2 |= SYS_IPRSTC2_I2C1_RST_Msk;
|
||||
SYS->IPRSTC2 &= ~SYS_IPRSTC2_I2C1_RST_Msk;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable I2Cx Module */
|
||||
I2C_DISABLE(i2cp->i2c);
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C0
|
||||
if (&I2CD0 == i2cp) {
|
||||
nvicDisableVector(NUMICRO_I2C0_IRQ_NUMBER);
|
||||
/* Disable I2C0 Module Clock */
|
||||
CLK->APBCLK &= ~CLK_APBCLK_I2C0_EN_Msk;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1
|
||||
if (&I2CD1 == i2cp) {
|
||||
nvicDisableVector(NUMICRO_I2C1_IRQ_NUMBER);
|
||||
/* Disable I2C1 Module Clock */
|
||||
CLK->APBCLK &= ~CLK_APBCLK_I2C1_EN_Msk;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static inline msg_t _i2c_txrx_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout) {
|
||||
|
||||
msg_t msg;
|
||||
// systime_t start, end;
|
||||
|
||||
i2cp->errors = I2C_NO_ERROR;
|
||||
i2cp->addr = addr;
|
||||
|
||||
i2cp->txbuf = txbuf;
|
||||
i2cp->txbytes = txbytes;
|
||||
i2cp->txidx = 0;
|
||||
|
||||
i2cp->rxbuf = rxbuf;
|
||||
i2cp->rxbytes = rxbytes;
|
||||
i2cp->rxidx = 0;
|
||||
|
||||
/* clear status flags */
|
||||
|
||||
/* acquire the bus */
|
||||
/* check to see if we already have the bus */
|
||||
if(i2cp->is_master) {
|
||||
|
||||
/* send repeated start */
|
||||
I2C_START(i2cp->i2c);
|
||||
while((uint8_t)I2C_GET_STATUS(i2cp->i2c) == 0xF8);
|
||||
|
||||
} else {
|
||||
/* unlock during the wait, so that tasks with
|
||||
* higher priority can get attention */
|
||||
// osalSysUnlock();
|
||||
|
||||
/* wait until the bus is released */
|
||||
/* Calculating the time window for the timeout on the busy bus condition.*/
|
||||
// start = osalOsGetSystemTimeX();
|
||||
// end = start + OSAL_MS2ST(NUMICRO_I2C_BUSY_TIMEOUT);
|
||||
uint8_t status = (uint8_t)(I2C_GET_STATUS(i2cp->i2c));
|
||||
if (status == 0x08 || status == 0x10) {
|
||||
i2cp->is_master = 1;
|
||||
I2C_EnableInt(i2cp->i2c);
|
||||
} else {
|
||||
I2C_Trigger(i2cp->i2c, /* Start */ 1, /* Stop */ 0, /* SI */ 1, /* Ack */ 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for the ISR to signal that the transmission (or receive if no transmission) phase is complete */
|
||||
|
||||
msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
|
||||
if (msg == MSG_TIMEOUT) {
|
||||
/* What to do here? */
|
||||
// I2C_DisableInt(i2cp->i2c);
|
||||
return msg;
|
||||
}
|
||||
i2cp->is_master = 0;
|
||||
|
||||
I2C_ClearTimeoutFlag(i2cp->i2c);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives data via the I2C bus as master.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
* @param[in] addr slave device address
|
||||
* @param[out] rxbuf pointer to the receive buffer
|
||||
* @param[in] rxbytes number of bytes to be received
|
||||
* @param[in] timeout the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval MSG_OK if the function succeeded.
|
||||
* @retval MSG_RESET if one or more I2C errors occurred, the errors can
|
||||
* be retrieved using @p i2cGetErrors().
|
||||
* @retval MSG_TIMEOUT if a timeout occurred before operation end. <b>After a
|
||||
* timeout the driver must be stopped and restarted
|
||||
* because the bus is in an uncertain state</b>.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout) {
|
||||
|
||||
i2cp->intstate = STATE_RECV;
|
||||
return _i2c_txrx_timeout(i2cp, addr, NULL, 0, rxbuf, rxbytes, timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmits data via the I2C bus as master.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
* @param[in] addr slave device address
|
||||
* @param[in] txbuf pointer to the transmit buffer
|
||||
* @param[in] txbytes number of bytes to be transmitted
|
||||
* @param[out] rxbuf pointer to the receive buffer
|
||||
* @param[in] rxbytes number of bytes to be received
|
||||
* @param[in] timeout the number of ticks before the operation timeouts,
|
||||
* the following special values are allowed:
|
||||
* - @a TIME_INFINITE no timeout.
|
||||
* .
|
||||
* @return The operation status.
|
||||
* @retval MSG_OK if the function succeeded.
|
||||
* @retval MSG_RESET if one or more I2C errors occurred, the errors can
|
||||
* be retrieved using @p i2cGetErrors().
|
||||
* @retval MSG_TIMEOUT if a timeout occurred before operation end. <b>After a
|
||||
* timeout the driver must be stopped and restarted
|
||||
* because the bus is in an uncertain state</b>.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout) {
|
||||
|
||||
i2cp->intstate = STATE_SEND;
|
||||
return _i2c_txrx_timeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, timeout);
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_I2C */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2019 Ein Terakawa
|
||||
Copyright (C) 2014-2015 Fabio Utzig
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file NUMICRO/hal_i2c_lld.h
|
||||
* @brief NUMICRO I2C subsystem low level driver header.
|
||||
*
|
||||
* @addtogroup I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_I2C_LLD_H_
|
||||
#define HAL_I2C_LLD_H_
|
||||
|
||||
#include "hal.h"
|
||||
#include "NUC123.h"
|
||||
|
||||
#if !defined(NUC123_I2C_USE_I2C0)
|
||||
#define NUC123_I2C_USE_I2C0 FALSE
|
||||
#endif
|
||||
|
||||
#if !defined(NUC123_I2C_USE_I2C1)
|
||||
#define NUC123_I2C_USE_I2C1 FALSE
|
||||
#endif
|
||||
|
||||
#define NUMICRO_HAS_I2C0 NUC123_HAS_I2C0
|
||||
#define NUMICRO_HAS_I2C1 NUC123_HAS_I2C1
|
||||
#define NUMICRO_I2C_USE_I2C0 NUC123_I2C_USE_I2C0
|
||||
#define NUMICRO_I2C_USE_I2C1 NUC123_I2C_USE_I2C1
|
||||
|
||||
|
||||
/**
|
||||
* @name Wakeup status codes
|
||||
* @{
|
||||
*/
|
||||
#define MSG_OK (msg_t)0 /**< @brief Normal wakeup message. */
|
||||
#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wakeup caused by a timeout
|
||||
condition. */
|
||||
#define MSG_RESET (msg_t)-2 /**< @brief Wakeup caused by a reset
|
||||
condition. */
|
||||
#define MSG_UNDEFINED (msg_t)-3
|
||||
|
||||
typedef int32_t msg_t; /**< Inter-thread message. */
|
||||
|
||||
#if !defined(CH_CFG_ST_FREQUENCY)
|
||||
#define CH_CFG_ST_FREQUENCY 1000
|
||||
#endif
|
||||
#define MS2ST(msec) \
|
||||
((systime_t)(((((uint32_t)(msec)) * \
|
||||
((uint32_t)CH_CFG_ST_FREQUENCY)) + 999UL) / 1000UL))
|
||||
typedef uint32_t systime_t;
|
||||
|
||||
#define NUMICRO_I2C0_IRQ_VECTOR NUC123_I2C0_HANDLER
|
||||
#define NUMICRO_I2C0_IRQ_NUMBER NUC123_I2C0_NUMBER
|
||||
#define NUMICRO_I2C1_IRQ_VECTOR NUC123_I2C1_HANDLER
|
||||
#define NUMICRO_I2C1_IRQ_NUMBER NUC123_I2C1_NUMBER
|
||||
|
||||
#define I2C_PCLK SystemCoreClock /* Assume APBDIV == 0 */
|
||||
// #define I2C_PCLK (SystemCoreClock/2) /* Assume APBDIV == 1 */
|
||||
|
||||
#if HAL_USE_I2C || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define STATE_STOP 0x00
|
||||
#define STATE_SEND 0x01
|
||||
#define STATE_RECV 0x02
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief I2C0 driver enable switch.
|
||||
* @details If set to @p TRUE the support for I2C0 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(NUMICRO_I2C_USE_I2C0) || defined(__DOXYGEN__)
|
||||
#define NUMICRO_I2C_USE_I2C0 FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 driver enable switch.
|
||||
* @details If set to @p TRUE the support for I2C1 is included.
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(NUMICRO_I2C_USE_I2C1) || defined(__DOXYGEN__)
|
||||
#define NUMICRO_I2C_USE_I2C1 FALSE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief I2C0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(NUMICRO_I2C_I2C0_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define NUMICRO_I2C_I2C0_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief I2C1 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(NUMICRO_I2C_I2C1_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define NUMICRO_I2C_I2C1_PRIORITY 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Timeout for external clearing BUSY bus (in ms).
|
||||
*/
|
||||
#if !defined(NUMICRO_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define NUMICRO_I2C_BUSY_TIMEOUT 50
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @brief error checks */
|
||||
#if NUMICRO_I2C_USE_I2C0 && !NUMICRO_HAS_I2C0
|
||||
#error "I2C0 not present in the selected device"
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1 && !NUMICRO_HAS_I2C1
|
||||
#error "I2C1 not present in the selected device"
|
||||
#endif
|
||||
|
||||
|
||||
#if !(NUMICRO_I2C_USE_I2C0 || NUMICRO_I2C_USE_I2C1)
|
||||
#error "I2C driver activated but no I2C peripheral assigned"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* @brief Type representing I2C address. */
|
||||
typedef uint8_t i2caddr_t;
|
||||
|
||||
/* @brief Type of I2C Driver condition flags. */
|
||||
typedef uint32_t i2cflags_t;
|
||||
|
||||
/* @brief Type used to control the ISR state machine. */
|
||||
typedef uint8_t intstate_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
* @note Implementations may extend this structure to contain more,
|
||||
* architecture dependent, fields.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct I2CConfig {
|
||||
|
||||
/* @brief Clock to be used for the I2C bus. */
|
||||
uint32_t clock;
|
||||
|
||||
} I2CConfig;
|
||||
|
||||
/**
|
||||
* @brief Type of a structure representing an I2C driver.
|
||||
*/
|
||||
typedef struct I2CDriver I2CDriver;
|
||||
|
||||
typedef I2C_T I2C_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief Structure representing an I2C driver.
|
||||
*/
|
||||
struct I2CDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
i2cstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const I2CConfig *config;
|
||||
/**
|
||||
* @brief Error flags.
|
||||
*/
|
||||
i2cflags_t errors;
|
||||
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Mutex protecting the bus.
|
||||
*/
|
||||
mutex_t mutex;
|
||||
#endif /* I2C_USE_MUTUAL_EXCLUSION */
|
||||
#if defined(I2C_DRIVER_EXT_FIELDS)
|
||||
I2C_DRIVER_EXT_FIELDS
|
||||
#endif
|
||||
/* @brief Thread waiting for I/O completion. */
|
||||
thread_reference_t thread;
|
||||
/* @brief Current slave address without R/W bit. */
|
||||
i2caddr_t addr;
|
||||
|
||||
/* End of the mandatory fields.*/
|
||||
|
||||
/* @brief Pointer to the buffer with data to send. */
|
||||
const uint8_t *txbuf;
|
||||
/* @brief Number of bytes of data to send. */
|
||||
size_t txbytes;
|
||||
/* @brief Current index in buffer when sending data. */
|
||||
size_t txidx;
|
||||
/* @brief Pointer to the buffer to put received data. */
|
||||
uint8_t *rxbuf;
|
||||
/* @brief Number of bytes of data to receive. */
|
||||
size_t rxbytes;
|
||||
/* @brief Current index in buffer when receiving data. */
|
||||
size_t rxidx;
|
||||
/* @brief Tracks current ISR state. */
|
||||
intstate_t intstate;
|
||||
/* @brief Low-level register access. */
|
||||
I2C_TypeDef *i2c;
|
||||
/* @brief If in master state or not. */
|
||||
uint8_t is_master;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Get errors from I2C driver.
|
||||
*
|
||||
* @param[in] i2cp pointer to the @p I2CDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C0
|
||||
extern I2CDriver I2CD0;
|
||||
#endif
|
||||
|
||||
#if NUMICRO_I2C_USE_I2C1
|
||||
extern I2CDriver I2CD1;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void i2c_lld_init(void);
|
||||
void i2c_lld_start(I2CDriver *i2cp);
|
||||
void i2c_lld_stop(I2CDriver *i2cp);
|
||||
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
const uint8_t *txbuf, size_t txbytes,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||||
uint8_t *rxbuf, size_t rxbytes,
|
||||
systime_t timeout);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_I2C */
|
||||
|
||||
#endif /* HAL_I2C_LLD_H_ */
|
||||
|
||||
/** @} */
|
|
@ -81,17 +81,17 @@
|
|||
/*
|
||||
* I2S units.
|
||||
*/
|
||||
#define NUC123_I2C1_HANDLER VectorB8
|
||||
#define NUC123_I2C1_NUMBER I2S_IRQn
|
||||
#define NUC123_I2S_HANDLER VectorB8
|
||||
#define NUC123_I2S_NUMBER I2S_IRQn
|
||||
|
||||
/*
|
||||
* I2C units.
|
||||
*/
|
||||
#define NUC123_I2C1_GLOBAL_HANDLER Vector88
|
||||
#define NUC123_I2C1_GLOBAL_NUMBER I2C0_IRQn
|
||||
#define NUC123_I2C0_HANDLER Vector88
|
||||
#define NUC123_I2C0_NUMBER I2C0_IRQn
|
||||
|
||||
#define NUC123_I2C2_GLOBAL_HANDLER Vector8C
|
||||
#define NUC123_I2C2_GLOBAL_NUMBER I2C1_IRQn
|
||||
#define NUC123_I2C1_HANDLER Vector8C
|
||||
#define NUC123_I2C1_NUMBER I2C1_IRQn
|
||||
|
||||
/*
|
||||
* TIM units.
|
||||
|
|
|
@ -112,20 +112,8 @@
|
|||
#define NUC123_HAS_GPIOK FALSE
|
||||
|
||||
/* I2C attributes.*/
|
||||
#define NUC123_HAS_I2C0 TRUE
|
||||
#define NUC123_HAS_I2C1 TRUE
|
||||
#define NUC123_I2C1_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 3)
|
||||
#define NUC123_I2C1_RX_DMA_CHN 0x00000200
|
||||
#define NUC123_I2C1_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 2)
|
||||
#define NUC123_I2C1_TX_DMA_CHN 0x00000020
|
||||
|
||||
#define NUC123_HAS_I2C2 TRUE
|
||||
#define NUC123_I2C2_RX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 5)
|
||||
#define NUC123_I2C2_RX_DMA_CHN 0x00020000
|
||||
#define NUC123_I2C2_TX_DMA_MSK NUC123_DMA_STREAM_ID_MSK(1, 4)
|
||||
#define NUC123_I2C2_TX_DMA_CHN 0x00002000
|
||||
|
||||
#define NUC123_HAS_I2C3 FALSE
|
||||
#define NUC123_HAS_I2C4 FALSE
|
||||
|
||||
/* QUADSPI attributes.*/
|
||||
#define NUC123_HAS_QUADSPI1 FALSE
|
||||
|
|
|
@ -16,6 +16,7 @@ include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/GPIOv1/driver.mk
|
|||
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/TIMv1/driver.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/USBv1/driver.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/SERIALv1/driver.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/LLD/I2Cv1/driver.mk
|
||||
|
||||
# Shared variables
|
||||
ALLCSRC += $(PLATFORMSRC)
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
##############################################################################
|
||||
# Build global options
|
||||
# NOTE: Can be overridden externally.
|
||||
#
|
||||
|
||||
# Compiler options here.
|
||||
ifeq ($(USE_OPT),)
|
||||
USE_OPT = -ggdb -g3 -gdwarf-3 -gstrict-dwarf -fomit-frame-pointer -falign-functions=16 -O
|
||||
endif
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
ifeq ($(USE_COPT),)
|
||||
USE_COPT =
|
||||
endif
|
||||
|
||||
# C++ specific options here (added to USE_OPT).
|
||||
ifeq ($(USE_CPPOPT),)
|
||||
USE_CPPOPT = -fno-rtti
|
||||
endif
|
||||
|
||||
# Enable this if you want the linker to remove unused code and data.
|
||||
ifeq ($(USE_LINK_GC),)
|
||||
USE_LINK_GC = yes
|
||||
endif
|
||||
|
||||
# Linker extra options here.
|
||||
ifeq ($(USE_LDOPT),)
|
||||
USE_LDOPT =
|
||||
endif
|
||||
|
||||
# Enable this if you want link time optimizations (LTO).
|
||||
ifeq ($(USE_LTO),)
|
||||
USE_LTO = yes
|
||||
endif
|
||||
|
||||
# Enable this if you want to see the full log while compiling.
|
||||
ifeq ($(USE_VERBOSE_COMPILE),)
|
||||
USE_VERBOSE_COMPILE = no
|
||||
endif
|
||||
|
||||
# If enabled, this option makes the build process faster by not compiling
|
||||
# modules not used in the current configuration.
|
||||
ifeq ($(USE_SMART_BUILD),)
|
||||
USE_SMART_BUILD = yes
|
||||
endif
|
||||
|
||||
#
|
||||
# Build global options
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Architecture or project specific options
|
||||
#
|
||||
|
||||
# Stack size to be allocated to the Cortex-M process stack. This stack is
|
||||
# the stack used by the main() thread.
|
||||
ifeq ($(USE_PROCESS_STACKSIZE),)
|
||||
USE_PROCESS_STACKSIZE = 0x400
|
||||
endif
|
||||
|
||||
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
|
||||
# stack is used for processing interrupts and exceptions.
|
||||
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
|
||||
USE_EXCEPTIONS_STACKSIZE = 0x400
|
||||
endif
|
||||
|
||||
# Enables the use of FPU (no, softfp, hard).
|
||||
ifeq ($(USE_FPU),)
|
||||
USE_FPU = no
|
||||
endif
|
||||
|
||||
# FPU-related options.
|
||||
ifeq ($(USE_FPU_OPT),)
|
||||
USE_FPU_OPT = -mfloat-abi=$(USE_FPU) -mfpu=fpv4-sp-d16
|
||||
endif
|
||||
|
||||
#
|
||||
# Architecture or project specific options
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Project, target, sources and paths
|
||||
#
|
||||
|
||||
# Define project name here
|
||||
PROJECT = ch
|
||||
|
||||
# Target settings.
|
||||
MCU = cortex-m0
|
||||
|
||||
# Imported source files and paths.
|
||||
BASE_PATH := ../../../../../../..
|
||||
CHIBIOS := $(BASE_PATH)/ChibiOS/ChibiOS
|
||||
CHIBIOS_CONTRIB := $(BASE_PATH)/ChibiOS/ChibiOS-Contrib
|
||||
CONFDIR := ./cfg
|
||||
BUILDDIR := ./build
|
||||
DEPDIR := ./.dep
|
||||
|
||||
# Licensing files.
|
||||
include $(CHIBIOS)/os/license/license.mk
|
||||
# Startup files.
|
||||
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_NUC123.mk
|
||||
# HAL-OSAL files (optional).
|
||||
include $(CHIBIOS)/os/hal/hal.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/ports/NUMICRO/NUC123/platform.mk
|
||||
include $(CHIBIOS_CONTRIB)/os/hal/boards/NUTINY-SDK-NUC123-V2.0/board.mk
|
||||
#include $(CHIBIOS)/os/hal/osal/os-less/ARMCMx/osal.mk
|
||||
include $(CHIBIOS)/os/hal/osal/rt-nil/osal.mk
|
||||
# RTOS files (optional).
|
||||
#include $(CHIBIOS)/os/nil/nil.mk
|
||||
include $(CHIBIOS)/os/rt/rt.mk
|
||||
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk
|
||||
#include $(CHIBIOS)/os/common/ports/ARMv7-M/compilers/GCC/mk/port.mk
|
||||
# Auto-build files in ./source recursively.
|
||||
include $(CHIBIOS)/tools/mk/autobuild.mk
|
||||
# Other files (optional).
|
||||
#include $(CHIBIOS)/test/lib/test.mk
|
||||
#include $(CHIBIOS)/test/rt/rt_test.mk
|
||||
#include $(CHIBIOS)/test/oslib/oslib_test.mk
|
||||
|
||||
# Define linker script file here
|
||||
LDSCRIPT= $(STARTUPLD_CONTRIB)/NUC123xD4xx0.ld
|
||||
|
||||
# C sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CSRC = $(ALLCSRC) \
|
||||
$(TESTSRC) \
|
||||
main.c \
|
||||
ssd1306.c
|
||||
|
||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CPPSRC = $(ALLCPPSRC)
|
||||
|
||||
# List ASM source files here.
|
||||
ASMSRC = $(ALLASMSRC)
|
||||
|
||||
# List ASM with preprocessor source files here.
|
||||
ASMXSRC = $(ALLXASMSRC)
|
||||
|
||||
# Inclusion directories.
|
||||
INCDIR = $(CONFDIR) $(ALLINC) $(TESTINC)
|
||||
|
||||
# Define C warning options here.
|
||||
CWARN = -Wall -Wextra -Wundef -Wstrict-prototypes
|
||||
|
||||
# Define C++ warning options here.
|
||||
CPPWARN = -Wall -Wextra -Wundef
|
||||
|
||||
#
|
||||
# Project, target, sources and paths
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Start of user section
|
||||
#
|
||||
|
||||
# List all user C define here, like -D_DEBUG=1
|
||||
UDEFS =
|
||||
|
||||
# Define ASM defines here
|
||||
UADEFS =
|
||||
|
||||
# List all user directories here
|
||||
UINCDIR =
|
||||
|
||||
# List the user directory to look for the libraries here
|
||||
ULIBDIR =
|
||||
|
||||
# List all user libraries here
|
||||
ULIBS =
|
||||
|
||||
#
|
||||
# End of user section
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Common rules
|
||||
#
|
||||
|
||||
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
|
||||
include $(RULESPATH)/arm-none-eabi.mk
|
||||
include $(RULESPATH)/rules.mk
|
||||
|
||||
#
|
||||
# Common rules
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Custom rules
|
||||
#
|
||||
|
||||
|
||||
OPENOCD:=$(shell readlink -f `which openocd`)
|
||||
OPENOCDPATH:=$(shell dirname $(OPENOCD))/../share/openocd
|
||||
|
||||
install-openocd-config:
|
||||
rm $(OPENOCDPATH)/scripts/target/numicroM0.cfg && cp $(CHIBIOS_CONTRIB)/ext/numicroM0.cfg $(OPENOCDPATH)/scripts/target/
|
||||
|
||||
connect:
|
||||
openocd -f ../scripts/interface/nulink.cfg -f ../scripts/target/numicroM0.cfg
|
||||
|
||||
flash: $(BUILDDIR)/$(PROJECT).elf
|
||||
openocd -f ../scripts/interface/nulink.cfg -f ../scripts/target/numicroM0.cfg -c "program $< verify reset exit"
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Custom rules
|
||||
##############################################################################
|
||||
|
|
@ -0,0 +1,773 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file rt/templates/chconf.h
|
||||
* @brief Configuration file template.
|
||||
* @details A copy of this file must be placed in each project directory, it
|
||||
* contains the application specific kernel settings.
|
||||
*
|
||||
* @addtogroup config
|
||||
* @details Kernel related settings and hooks.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHCONF_H
|
||||
#define CHCONF_H
|
||||
|
||||
#define _CHIBIOS_RT_CONF_
|
||||
#define _CHIBIOS_RT_CONF_VER_6_1_
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name System timers settings
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief System time counter resolution.
|
||||
* @note Allowed values are 16 or 32 bits.
|
||||
*/
|
||||
#if !defined(CH_CFG_ST_RESOLUTION)
|
||||
#define CH_CFG_ST_RESOLUTION 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief System tick frequency.
|
||||
* @details Frequency of the system timer that drives the system ticks. This
|
||||
* setting also defines the system tick time unit.
|
||||
*/
|
||||
#if !defined(CH_CFG_ST_FREQUENCY)
|
||||
#define CH_CFG_ST_FREQUENCY 10000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Time intervals data size.
|
||||
* @note Allowed values are 16, 32 or 64 bits.
|
||||
*/
|
||||
#if !defined(CH_CFG_INTERVALS_SIZE)
|
||||
#define CH_CFG_INTERVALS_SIZE 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Time types data size.
|
||||
* @note Allowed values are 16 or 32 bits.
|
||||
*/
|
||||
#if !defined(CH_CFG_TIME_TYPES_SIZE)
|
||||
#define CH_CFG_TIME_TYPES_SIZE 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Time delta constant for the tick-less mode.
|
||||
* @note If this value is zero then the system uses the classic
|
||||
* periodic tick. This value represents the minimum number
|
||||
* of ticks that is safe to specify in a timeout directive.
|
||||
* The value one is not valid, timeouts are rounded up to
|
||||
* this value.
|
||||
*/
|
||||
#if !defined(CH_CFG_ST_TIMEDELTA)
|
||||
#define CH_CFG_ST_TIMEDELTA 0
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Kernel parameters and options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Round robin interval.
|
||||
* @details This constant is the number of system ticks allowed for the
|
||||
* threads before preemption occurs. Setting this value to zero
|
||||
* disables the preemption for threads with equal priority and the
|
||||
* round robin becomes cooperative. Note that higher priority
|
||||
* threads can still preempt, the kernel is always preemptive.
|
||||
* @note Disabling the round robin preemption makes the kernel more compact
|
||||
* and generally faster.
|
||||
* @note The round robin preemption is not supported in tickless mode and
|
||||
* must be set to zero in that case.
|
||||
*/
|
||||
#if !defined(CH_CFG_TIME_QUANTUM)
|
||||
#define CH_CFG_TIME_QUANTUM 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Idle thread automatic spawn suppression.
|
||||
* @details When this option is activated the function @p chSysInit()
|
||||
* does not spawn the idle thread. The application @p main()
|
||||
* function becomes the idle thread and must implement an
|
||||
* infinite loop.
|
||||
*/
|
||||
#if !defined(CH_CFG_NO_IDLE_THREAD)
|
||||
#define CH_CFG_NO_IDLE_THREAD FALSE
|
||||
#endif
|
||||
|
||||
#if !defined(CH_CFG_MAX_THREADS)
|
||||
#define CH_CFG_MAX_THREADS 8
|
||||
#endif
|
||||
|
||||
#if !defined(CH_CFG_AUTOSTART_THREADS)
|
||||
#define CH_CFG_AUTOSTART_THREADS TRUE
|
||||
#endif
|
||||
|
||||
#if !defined(CH_CFG_THREAD_EXT_FIELDS)
|
||||
#define CH_CFG_THREAD_EXT_FIELDS /* Add threads custom fields here.*/
|
||||
#endif
|
||||
|
||||
#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \
|
||||
/* Add custom threads initialization code here.*/ \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Performance options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief OS optimization.
|
||||
* @details If enabled then time efficient rather than space efficient code
|
||||
* is used when two possible implementations exist.
|
||||
*
|
||||
* @note This is not related to the compiler optimization options.
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_OPTIMIZE_SPEED)
|
||||
#define CH_CFG_OPTIMIZE_SPEED TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Subsystem options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Time Measurement APIs.
|
||||
* @details If enabled then the time measurement APIs are included in
|
||||
* the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_TM)
|
||||
#define CH_CFG_USE_TM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Threads registry APIs.
|
||||
* @details If enabled then the registry APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_REGISTRY)
|
||||
#define CH_CFG_USE_REGISTRY TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Threads synchronization APIs.
|
||||
* @details If enabled then the @p chThdWait() function is included in
|
||||
* the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_WAITEXIT)
|
||||
#define CH_CFG_USE_WAITEXIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Semaphores APIs.
|
||||
* @details If enabled then the Semaphores APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_SEMAPHORES)
|
||||
#define CH_CFG_USE_SEMAPHORES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Semaphores queuing mode.
|
||||
* @details If enabled then the threads are enqueued on semaphores by
|
||||
* priority rather than in FIFO order.
|
||||
*
|
||||
* @note The default is @p FALSE. Enable this if you have special
|
||||
* requirements.
|
||||
* @note Requires @p CH_CFG_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
|
||||
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Mutexes APIs.
|
||||
* @details If enabled then the mutexes APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MUTEXES)
|
||||
#define CH_CFG_USE_MUTEXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables recursive behavior on mutexes.
|
||||
* @note Recursive mutexes are heavier and have an increased
|
||||
* memory footprint.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
* @note Requires @p CH_CFG_USE_MUTEXES.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
|
||||
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Conditional Variables APIs.
|
||||
* @details If enabled then the conditional variables APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_MUTEXES.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_CONDVARS)
|
||||
#define CH_CFG_USE_CONDVARS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Conditional Variables APIs with timeout.
|
||||
* @details If enabled then the conditional variables APIs with timeout
|
||||
* specification are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_CONDVARS.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
|
||||
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Events Flags APIs.
|
||||
* @details If enabled then the event flags APIs are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_EVENTS)
|
||||
#define CH_CFG_USE_EVENTS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Events Flags APIs with timeout.
|
||||
* @details If enabled then the events APIs with timeout specification
|
||||
* are included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_EVENTS.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
|
||||
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Synchronous Messages APIs.
|
||||
* @details If enabled then the synchronous messages APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MESSAGES)
|
||||
#define CH_CFG_USE_MESSAGES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Synchronous Messages queuing mode.
|
||||
* @details If enabled then messages are served by priority rather than in
|
||||
* FIFO order.
|
||||
*
|
||||
* @note The default is @p FALSE. Enable this if you have special
|
||||
* requirements.
|
||||
* @note Requires @p CH_CFG_USE_MESSAGES.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
|
||||
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Dynamic Threads APIs.
|
||||
* @details If enabled then the dynamic threads creation APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_WAITEXIT.
|
||||
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_DYNAMIC)
|
||||
#define CH_CFG_USE_DYNAMIC TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name OSLIB options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Mailboxes APIs.
|
||||
* @details If enabled then the asynchronous messages (mailboxes) APIs are
|
||||
* included in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_SEMAPHORES.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MAILBOXES)
|
||||
#define CH_CFG_USE_MAILBOXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Core Memory Manager APIs.
|
||||
* @details If enabled then the core memory manager APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MEMCORE)
|
||||
#define CH_CFG_USE_MEMCORE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Managed RAM size.
|
||||
* @details Size of the RAM area to be managed by the OS. If set to zero
|
||||
* then the whole available RAM is used. The core memory is made
|
||||
* available to the heap allocator and/or can be used directly through
|
||||
* the simplified core memory allocator.
|
||||
*
|
||||
* @note In order to let the OS manage the whole RAM the linker script must
|
||||
* provide the @p __heap_base__ and @p __heap_end__ symbols.
|
||||
* @note Requires @p CH_CFG_USE_MEMCORE.
|
||||
*/
|
||||
#if !defined(CH_CFG_MEMCORE_SIZE)
|
||||
#define CH_CFG_MEMCORE_SIZE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Heap Allocator APIs.
|
||||
* @details If enabled then the memory heap allocator APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
|
||||
* @p CH_CFG_USE_SEMAPHORES.
|
||||
* @note Mutexes are recommended.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_HEAP)
|
||||
#define CH_CFG_USE_HEAP TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Memory Pools Allocator APIs.
|
||||
* @details If enabled then the memory pools allocator APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_MEMPOOLS)
|
||||
#define CH_CFG_USE_MEMPOOLS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Objects FIFOs APIs.
|
||||
* @details If enabled then the objects FIFOs APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_OBJ_FIFOS)
|
||||
#define CH_CFG_USE_OBJ_FIFOS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Pipes APIs.
|
||||
* @details If enabled then the pipes APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_PIPES)
|
||||
#define CH_CFG_USE_PIPES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Objects Caches APIs.
|
||||
* @details If enabled then the objects caches APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_OBJ_CACHES)
|
||||
#define CH_CFG_USE_OBJ_CACHES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delegate threads APIs.
|
||||
* @details If enabled then the delegate threads APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_DELEGATES)
|
||||
#define CH_CFG_USE_DELEGATES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Jobs Queues APIs.
|
||||
* @details If enabled then the jobs queues APIs are included
|
||||
* in the kernel.
|
||||
*
|
||||
* @note The default is @p TRUE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_JOBS)
|
||||
#define CH_CFG_USE_JOBS TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Objects factory options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Objects Factory APIs.
|
||||
* @details If enabled then the objects factory APIs are included in the
|
||||
* kernel.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_CFG_USE_FACTORY)
|
||||
#define CH_CFG_USE_FACTORY TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum length for object names.
|
||||
* @details If the specified length is zero then the name is stored by
|
||||
* pointer but this could have unintended side effects.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
|
||||
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the registry of generic objects.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
|
||||
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables factory for generic buffers.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
|
||||
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables factory for semaphores.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
|
||||
#define CH_CFG_FACTORY_SEMAPHORES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables factory for mailboxes.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_MAILBOXES)
|
||||
#define CH_CFG_FACTORY_MAILBOXES TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables factory for objects FIFOs.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
|
||||
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables factory for Pipes.
|
||||
*/
|
||||
#if !defined(CH_CFG_FACTORY_PIPES) || defined(__DOXYGEN__)
|
||||
#define CH_CFG_FACTORY_PIPES TRUE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Debug options
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Debug option, kernel statistics.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_STATISTICS)
|
||||
#define CH_DBG_STATISTICS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, system state check.
|
||||
* @details If enabled the correct call protocol for system APIs is checked
|
||||
* at runtime.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
|
||||
#define CH_DBG_SYSTEM_STATE_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, parameters checks.
|
||||
* @details If enabled then the checks on the API functions input
|
||||
* parameters are activated.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_CHECKS)
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, consistency checks.
|
||||
* @details If enabled then all the assertions in the kernel code are
|
||||
* activated. This includes consistency checks inside the kernel,
|
||||
* runtime anomalies and port-defined checks.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_ASSERTS)
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, trace buffer.
|
||||
* @details If enabled then the trace buffer is activated.
|
||||
*
|
||||
* @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
|
||||
*/
|
||||
#if !defined(CH_DBG_TRACE_MASK)
|
||||
#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Trace buffer entries.
|
||||
* @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
|
||||
* different from @p CH_DBG_TRACE_MASK_DISABLED.
|
||||
*/
|
||||
#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
|
||||
#define CH_DBG_TRACE_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, stack checks.
|
||||
* @details If enabled then a runtime stack check is performed.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
* @note The stack check is performed in a architecture/port dependent way.
|
||||
* It may not be implemented or some ports.
|
||||
* @note The default failure mode is to halt the system with the global
|
||||
* @p panic_msg variable set to @p NULL.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
|
||||
#define CH_DBG_ENABLE_STACK_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, stacks initialization.
|
||||
* @details If enabled then the threads working area is filled with a byte
|
||||
* value when a thread is created. This can be useful for the
|
||||
* runtime measurement of the used stack.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_FILL_THREADS)
|
||||
#define CH_DBG_FILL_THREADS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Debug option, threads profiling.
|
||||
* @details If enabled then a field is added to the @p thread_t structure that
|
||||
* counts the system ticks occurred while executing the thread.
|
||||
*
|
||||
* @note The default is @p FALSE.
|
||||
* @note This debug option is not currently compatible with the
|
||||
* tickless mode.
|
||||
*/
|
||||
#if !defined(CH_DBG_THREADS_PROFILING)
|
||||
#define CH_DBG_THREADS_PROFILING FALSE
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @name Kernel hooks
|
||||
* @{
|
||||
*/
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief System structure extension.
|
||||
* @details User fields added to the end of the @p ch_system_t structure.
|
||||
*/
|
||||
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
|
||||
/* Add threads custom fields here.*/
|
||||
|
||||
/**
|
||||
* @brief System initialization hook.
|
||||
* @details User initialization code added to the @p chSysInit() function
|
||||
* just before interrupts are enabled globally.
|
||||
*/
|
||||
#define CH_CFG_SYSTEM_INIT_HOOK() { \
|
||||
/* Add threads initialization code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Threads descriptor structure extension.
|
||||
* @details User fields added to the end of the @p thread_t structure.
|
||||
*/
|
||||
#define CH_CFG_THREAD_EXTRA_FIELDS \
|
||||
/* Add threads custom fields here.*/
|
||||
|
||||
/**
|
||||
* @brief Threads initialization hook.
|
||||
* @details User initialization code added to the @p _thread_init() function.
|
||||
*
|
||||
* @note It is invoked from within @p _thread_init() and implicitly from all
|
||||
* the threads creation APIs.
|
||||
*/
|
||||
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
|
||||
/* Add threads initialization code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Threads finalization hook.
|
||||
* @details User finalization code added to the @p chThdExit() API.
|
||||
*/
|
||||
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
|
||||
/* Add threads finalization code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Context switch hook.
|
||||
* @details This hook is invoked just before switching between threads.
|
||||
*/
|
||||
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
|
||||
/* Context switch code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ISR enter hook.
|
||||
*/
|
||||
#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
|
||||
/* IRQ prologue code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ISR exit hook.
|
||||
*/
|
||||
#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
|
||||
/* IRQ epilogue code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Idle thread enter hook.
|
||||
* @note This hook is invoked within a critical zone, no OS functions
|
||||
* should be invoked from here.
|
||||
* @note This macro can be used to activate a power saving mode.
|
||||
*/
|
||||
#define CH_CFG_IDLE_ENTER_HOOK() { \
|
||||
/* Idle-enter code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Idle thread leave hook.
|
||||
* @note This hook is invoked within a critical zone, no OS functions
|
||||
* should be invoked from here.
|
||||
* @note This macro can be used to deactivate a power saving mode.
|
||||
*/
|
||||
#define CH_CFG_IDLE_LEAVE_HOOK() { \
|
||||
/* Idle-leave code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Idle Loop hook.
|
||||
* @details This hook is continuously invoked by the idle thread loop.
|
||||
*/
|
||||
#define CH_CFG_IDLE_LOOP_HOOK() { \
|
||||
/* Idle loop code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System tick event hook.
|
||||
* @details This hook is invoked in the system tick handler immediately
|
||||
* after processing the virtual timers queue.
|
||||
*/
|
||||
#define CH_CFG_SYSTEM_TICK_HOOK() { \
|
||||
/* System tick event code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief System halt hook.
|
||||
* @details This hook is invoked in case to a system halting error before
|
||||
* the system is halted.
|
||||
*/
|
||||
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
|
||||
/* System halt code here.*/ \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trace hook.
|
||||
* @details This hook is invoked each time a new record is written in the
|
||||
* trace buffer.
|
||||
*/
|
||||
#define CH_CFG_TRACE_HOOK(tep) { \
|
||||
/* Trace code here.*/ \
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Port-specific settings (override port settings defaulted in chcore.h). */
|
||||
/*===========================================================================*/
|
||||
|
||||
#endif /* CHCONF_H */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2020 Alex Lewontin
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/halconf.h
|
||||
* @brief HAL configuration header.
|
||||
* @details HAL configuration file, this file allows to enable or disable the
|
||||
* various device drivers from your application. You may also use
|
||||
* this file in order to override the device drivers default settings.
|
||||
*
|
||||
* @addtogroup HAL_CONF
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HALCONF_H
|
||||
#define HALCONF_H
|
||||
|
||||
#define _CHIBIOS_HAL_CONF_
|
||||
#define _CHIBIOS_HAL_CONF_VER_7_1_
|
||||
|
||||
#include "mcuconf.h"
|
||||
|
||||
/**
|
||||
* @brief Enables the PAL subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_PAL TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ADC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_ADC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the CAN subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_CAN FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the cryptographic subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_CRY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the DAC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_DAC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the EFlash subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_EFL) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_EFL FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the GPT subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_GPT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the I2C subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_I2C TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the I2S subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_I2S FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ICU subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_ICU FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_MAC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MMC_SPI subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_MMC_SPI FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the PWM subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_PWM FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the RTC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_RTC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SDC subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SDC FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SERIAL FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL over USB subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SERIAL_USB FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SIO subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SIO FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SPI subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_SPI FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the TRNG subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_TRNG FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the UART subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_UART FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the USB subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_USB FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the WDG subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_WDG FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the WSPI subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_WSPI FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* PAL driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
|
||||
#define PAL_USE_CALLBACKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define PAL_USE_WAIT FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* ADC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define ADC_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define ADC_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* CAN driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Sleep mode related APIs inclusion switch.
|
||||
*/
|
||||
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
|
||||
#define CAN_USE_SLEEP_MODE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enforces the driver to use direct callbacks rather than OSAL events.
|
||||
*/
|
||||
#if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
|
||||
#define CAN_ENFORCE_USE_CALLBACKS FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* CRY driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the SW fall-back of the cryptographic driver.
|
||||
* @details When enabled, this option, activates a fall-back software
|
||||
* implementation for algorithms not supported by the underlying
|
||||
* hardware.
|
||||
* @note Fall-back implementations may not be present for all algorithms.
|
||||
*/
|
||||
#if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
|
||||
#define HAL_CRY_USE_FALLBACK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Makes the driver forcibly use the fall-back implementations.
|
||||
*/
|
||||
#if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
|
||||
#define HAL_CRY_ENFORCE_FALLBACK FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* DAC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define DAC_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I2C driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the mutual exclusion APIs on the I2C bus.
|
||||
*/
|
||||
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define I2C_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MAC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the zero-copy API.
|
||||
*/
|
||||
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
|
||||
#define MAC_USE_ZERO_COPY FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables an event sources for incoming packets.
|
||||
*/
|
||||
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
|
||||
#define MAC_USE_EVENTS TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MMC_SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
* This option is recommended also if the SPI driver does not
|
||||
* use a DMA channel and heavily loads the CPU.
|
||||
*/
|
||||
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
#define MMC_NICE_WAITING TRUE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SDC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Number of initialization attempts before rejecting the card.
|
||||
* @note Attempts are performed at 10mS intervals.
|
||||
*/
|
||||
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
|
||||
#define SDC_INIT_RETRY 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Include support for MMC cards.
|
||||
* @note MMC support is not yet implemented so this option must be kept
|
||||
* at @p FALSE.
|
||||
*/
|
||||
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
|
||||
#define SDC_MMC_SUPPORT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
*/
|
||||
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
#define SDC_NICE_WAITING TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief OCR initialization constant for V20 cards.
|
||||
*/
|
||||
#if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
|
||||
#define SDC_INIT_OCR_V20 0x50FF8000U
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief OCR initialization constant for non-V20 cards.
|
||||
*/
|
||||
#if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
|
||||
#define SDC_INIT_OCR 0x80100000U
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SERIAL driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Default bit rate.
|
||||
* @details Configuration parameter, this is the baud rate selected for the
|
||||
* default configuration.
|
||||
*/
|
||||
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_DEFAULT_BITRATE 38400
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Serial buffers size.
|
||||
* @details Configuration parameter, you can change the depth of the queue
|
||||
* buffers depending on the requirements of your application.
|
||||
* @note The default is 16 bytes for both the transmission and receive
|
||||
* buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_BUFFERS_SIZE 32
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SERIAL_USB driver related setting. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Serial over USB buffers size.
|
||||
* @details Configuration parameter, the buffer size must be a multiple of
|
||||
* the USB data endpoint maximum packet size.
|
||||
* @note The default is 256 bytes for both the transmission and receive
|
||||
* buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SERIAL_USB_BUFFERS_SIZE 256
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Serial over USB number of buffers.
|
||||
* @note The default is 2 buffers.
|
||||
*/
|
||||
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
|
||||
#define SERIAL_USB_BUFFERS_NUMBER 2
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define SPI_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables circular transfers APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
|
||||
#define SPI_USE_CIRCULAR FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define SPI_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Handling method for SPI CS line.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
|
||||
#define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* UART driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define UART_USE_WAIT FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define UART_USE_MUTUAL_EXCLUSION FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* USB driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define USB_USE_WAIT FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* WSPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
|
||||
#define WSPI_USE_WAIT TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
#define WSPI_USE_MUTUAL_EXCLUSION TRUE
|
||||
#endif
|
||||
|
||||
#endif /* HALCONF_H */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright (C) 2016 Stephane D'Alu
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _MCUCONF_H_
|
||||
#define _MCUCONF_H_
|
||||
|
||||
/*
|
||||
* Board setting
|
||||
*/
|
||||
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
|
||||
#define NUC123_I2C_USE_I2C0 TRUE
|
||||
#define NUC123_I2C_USE_I2C1 TRUE
|
||||
|
||||
#define NUC123_MCUCONF
|
||||
|
||||
#endif /* _MCUCONF_H_ */
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/halconf.h
|
||||
* @brief Bare-metal OSAL configuration header.
|
||||
*
|
||||
* @addtogroup OSAL_CONF
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef OSALCONF_H
|
||||
#define OSALCONF_H
|
||||
|
||||
/**
|
||||
* @brief Frequency in Hertz of the system tick.
|
||||
*/
|
||||
#if !defined(OSAL_ST_FREQUENCY) || defined(__DOXYGEN__)
|
||||
#define OSAL_ST_FREQUENCY 10000
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables OSAL assertions.
|
||||
*/
|
||||
#if !defined(OSAL_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
|
||||
#define OSAL_DBG_ENABLE_ASSERTS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enables OSAL functions parameters checks.
|
||||
*/
|
||||
#if !defined(OSAL_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
|
||||
#define OSAL_DBG_ENABLE_CHECKS FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief OSAL initialization hook.
|
||||
*/
|
||||
#if !defined(OSAL_INIT_HOOK) || defined(__DOXYGEN__)
|
||||
#define OSAL_INIT_HOOK() { \
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Idle loop hook macro.
|
||||
*/
|
||||
#if !defined(OSAL_IDLE_HOOK) || defined(__DOXYGEN__)
|
||||
#define OSAL_IDLE_HOOK() { \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OSALCONF_H */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,239 @@
|
|||
|
||||
/*
|
||||
Copyright (C) 2020 Ein Terakawa
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
#include "ssd1306.h"
|
||||
|
||||
static const uint8_t logo_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x80, 0xF0, 0xF8, 0xFC, 0xFC,
|
||||
0xFE, 0x3E, 0x1E, 0x1E, 0x7E, 0x7C, 0x7C, 0x78,
|
||||
0x70, 0x40, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0x00,
|
||||
0x00, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0x00, 0x00,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xC0, 0xE0, 0xE0,
|
||||
0xE0, 0xC0, 0x00, 0x00, 0xEE, 0xEE, 0xEE, 0xEE,
|
||||
0xEE, 0x00, 0x80, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE,
|
||||
0x1E, 0x1E, 0x1E, 0xFE, 0xFC, 0xFC, 0xF8, 0xF0,
|
||||
0x80, 0x60, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xDE,
|
||||
0x9E, 0xBE, 0xBC, 0xBC, 0x38, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x01, 0x0F, 0x1F, 0x3F, 0x3F,
|
||||
0x7F, 0x7C, 0x78, 0x78, 0x7E, 0x3E, 0x3E, 0x3E,
|
||||
0x0E, 0x02, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F,
|
||||
0x7F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00,
|
||||
0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00,
|
||||
0x7F, 0x7F, 0x7F, 0x7F, 0x1F, 0x79, 0x7F, 0x7F,
|
||||
0x7F, 0x3F, 0x0F, 0x00, 0x7F, 0x7F, 0x7F, 0x7F,
|
||||
0x7F, 0x00, 0x01, 0x0F, 0x1F, 0x3F, 0x3F, 0x7F,
|
||||
0x78, 0x78, 0x78, 0x7F, 0x3F, 0x3F, 0x1F, 0x0F,
|
||||
0x01, 0x04, 0x1C, 0x3D, 0x3D, 0x7D, 0x79, 0x7B,
|
||||
0x7B, 0x7F, 0x7F, 0x3F, 0x1F, 0x0C, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xF8, 0xC0, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0x00, 0x80, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE,
|
||||
0x3E, 0x1E, 0x1E, 0x7E, 0x7C, 0x7C, 0x78, 0x70,
|
||||
0x40, 0x00, 0x38, 0x38, 0x38, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x20, 0x38, 0x3C,
|
||||
0x3C, 0x3E, 0x9E, 0x9E, 0xFE, 0xFE, 0xFC, 0xF8,
|
||||
0x70, 0x00, 0x20, 0x38, 0x3C, 0xFC, 0xFE, 0xDE,
|
||||
0xDE, 0xFE, 0xFE, 0x7C, 0x78, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F,
|
||||
0x7F, 0x01, 0x07, 0x1F, 0x7F, 0x7F, 0x7F, 0x7F,
|
||||
0x7F, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F,
|
||||
0x7F, 0x7C, 0x7C, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F,
|
||||
0x03, 0x00, 0x01, 0x0F, 0x1F, 0x3F, 0x3F, 0x7F,
|
||||
0x7C, 0x78, 0x78, 0x7E, 0x3E, 0x3E, 0x3E, 0x0E,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F,
|
||||
0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x70, 0x7C, 0x7E,
|
||||
0x7F, 0x7F, 0x7F, 0x7F, 0x7B, 0x7B, 0x79, 0x79,
|
||||
0x78, 0x00, 0x04, 0x1C, 0x3C, 0x7D, 0x79, 0x79,
|
||||
0x79, 0x7F, 0x7F, 0x3F, 0x3F, 0x0E, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static void draw_logo(SSD1306_DRIVER *ssd1306, bool invert, char xx) {
|
||||
uint8_t width = ssd1306->width;
|
||||
uint8_t height = ssd1306->height;
|
||||
uint8_t num_pages = height / 8;
|
||||
uint8_t invert_bits = invert ? 0xff : 0x00;
|
||||
uint8_t *buf = SSD1306_GET_FRAMEBUFFER(ssd1306);
|
||||
|
||||
for (uint8_t row = 0; row < num_pages; ++row) {
|
||||
for (uint8_t x = 0; x < width; ++x) {
|
||||
uint8_t dat = logo_bits[(128 - xx + x) % 128 + (row % 4) * width];
|
||||
if (row / 2 % 2 == 0) {
|
||||
dat ^= 0xff;
|
||||
}
|
||||
dat ^= invert_bits; /* Invert Imeage Bits */
|
||||
if (true) {
|
||||
/* Horizontal Addressing Mode */
|
||||
buf[row * width + x] = dat;
|
||||
} else {
|
||||
/* Vertical Addressing Mode */
|
||||
buf[x * num_pages + row] = dat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define I2C_CLK_FREQ 1000000
|
||||
static const I2CConfig i2ccfg = { I2C_CLK_FREQ };
|
||||
#if NUC123_I2C_USE_I2C0
|
||||
DEFINE_SSD1306_DRIVER(ssd1306_128x64, &I2CD0, SSD1306_ADDRESS, 128, 64, false);
|
||||
#endif
|
||||
#if NUC123_I2C_USE_I2C1
|
||||
DEFINE_SSD1306_DRIVER(ssd1306_128x32, &I2CD1, SSD1306_ADDRESS, 128, 32, true);
|
||||
#endif
|
||||
|
||||
#if I2C_USE_MUTUAL_EXCLUSION
|
||||
#define ACQUIRE_BUS(oled_driver) i2cAcquireBus((oled_driver)->i2cd)
|
||||
#define RELEASE_BUS(oled_driver) i2cReleaseBus((oled_driver)->i2cd)
|
||||
#else
|
||||
#define ACQUIRE_BUS(oled_driver)
|
||||
#define RELEASE_BUS(oled_driver)
|
||||
#endif
|
||||
|
||||
thread_reference_t thread1_ref = NULL;
|
||||
|
||||
static THD_WORKING_AREA(waThread1, 128);
|
||||
static THD_FUNCTION(Thread1, arg) {
|
||||
chRegSetThreadName("blinker");
|
||||
|
||||
(void)arg;
|
||||
while (true) {
|
||||
if(osalThreadSuspendS(&thread1_ref) == MSG_OK) {
|
||||
OnboardLED_On();
|
||||
}else{
|
||||
OnboardLED_Off();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define I2C_THREAD_STACK_SIZE 256
|
||||
#if NUC123_I2C_USE_I2C0
|
||||
static THD_WORKING_AREA(waThread2, I2C_THREAD_STACK_SIZE);
|
||||
static THD_FUNCTION(Thread2, arg) {
|
||||
chRegSetThreadName("oled1");
|
||||
|
||||
SSD1306_DRIVER *ssd1306 = (SSD1306_DRIVER *)arg;
|
||||
ssd1306->i2ccfg = &i2ccfg;
|
||||
ACQUIRE_BUS(ssd1306);
|
||||
ssd1306_init(ssd1306);
|
||||
RELEASE_BUS(ssd1306);
|
||||
char x = 0;
|
||||
while (true) {
|
||||
osalThreadSleepMilliseconds(127);
|
||||
bool invert = false;
|
||||
draw_logo(ssd1306, invert, x);
|
||||
ACQUIRE_BUS(ssd1306);
|
||||
ssd1306_data(ssd1306);
|
||||
/* RELEASE_BUS(ssd1306); */
|
||||
/* ACQUIRE_BUS(ssd1306); */
|
||||
if (x % 16 == 12) {
|
||||
ssd1306_display_off(ssd1306);
|
||||
} else if (x % 16 == 0) {
|
||||
ssd1306_display_on(ssd1306);
|
||||
}
|
||||
RELEASE_BUS(ssd1306);
|
||||
x = (x + 1) % 128;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NUC123_I2C_USE_I2C1
|
||||
static THD_WORKING_AREA(waThread3, I2C_THREAD_STACK_SIZE);
|
||||
static THD_FUNCTION(Thread3, arg) {
|
||||
chRegSetThreadName("oled2");
|
||||
|
||||
SSD1306_DRIVER *ssd1306 = (SSD1306_DRIVER *)arg;
|
||||
ssd1306->i2ccfg = &i2ccfg;
|
||||
ACQUIRE_BUS(ssd1306);
|
||||
#if true
|
||||
/* Workaround for some 128x32 OLED modules typically with black PCB. */
|
||||
while (!ssd1306_init(ssd1306)) {
|
||||
RELEASE_BUS(ssd1306);
|
||||
osalThreadSleepMilliseconds(100);
|
||||
ACQUIRE_BUS(ssd1306);
|
||||
}
|
||||
#endif
|
||||
ssd1306_init(ssd1306);
|
||||
RELEASE_BUS(ssd1306);
|
||||
char x = 0;
|
||||
while (true) {
|
||||
osalThreadSleepMilliseconds(131);
|
||||
bool invert = true;
|
||||
draw_logo(ssd1306, invert, x);
|
||||
ACQUIRE_BUS(ssd1306);
|
||||
ssd1306_data(ssd1306);
|
||||
RELEASE_BUS(ssd1306);
|
||||
x = (x - 1) % 128;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Application entry point.
|
||||
*/
|
||||
int main(void) {
|
||||
|
||||
/*
|
||||
* System initializations.
|
||||
* - HAL initialization, this also initializes the configured device drivers
|
||||
* and performs the board-specific initializations.
|
||||
*/
|
||||
halInit();
|
||||
|
||||
/*
|
||||
* chSysInit() will also enable interrupts.
|
||||
*/
|
||||
chSysInit();
|
||||
|
||||
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 2, Thread1, NULL);
|
||||
#if NUC123_I2C_USE_I2C0
|
||||
chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO + 1, Thread2, &ssd1306_128x64);
|
||||
#endif
|
||||
#if NUC123_I2C_USE_I2C1
|
||||
chThdCreateStatic(waThread3, sizeof(waThread3), NORMALPRIO + 1, Thread3, &ssd1306_128x32);
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
osalThreadResumeS(&thread1_ref, MSG_OK);
|
||||
osalThreadSleepMilliseconds(100);
|
||||
osalThreadResumeS(&thread1_ref, MSG_RESET);
|
||||
osalThreadSleepMilliseconds(400);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
*****************************************************************************
|
||||
** ChibiOS/HAL - I2C driver demo for NUC123. **
|
||||
*****************************************************************************
|
||||
|
||||
** TARGET **
|
||||
|
||||
The demo runs on a NUTINY-SDK-NUC123-V2.0 board with a NUC123SD4AN0 MCU.
|
||||
|
||||
** The Demo **
|
||||
|
||||
The application demonstrates the use of the NUC123 platform driver, and a little
|
||||
bit of the PAL. A successful run of the test involves the on-board LED blinking at 2 Hz
|
||||
(on for 100 ms, then off for 400 ms).
|
||||
|
||||
|
||||
** Board Setup **
|
||||
|
||||
- Connect 128x32 OLED module to PA.10=I2C1_SDA and PA.11=I2C1_SCL .
|
||||
- Connect 128x64 OLED module to PF.2=I2C0_SDA and PF.3=I2C0_SCL .
|
||||
- If any of the OLED modules are absent, pull-up resistors are required instead.
|
||||
|
||||
** Build Procedure **
|
||||
|
||||
The demo has been tested using gcc version 9.3.1 (GNU Arm Embedded Toolchain 9-2020-q2-update).
|
||||
Just add overriding setting for TRGT in the command line in order to use specific version of GCC.
|
||||
for example: make -j TRGT=/opt/ARM/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi-
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
Copyright (C) 2020 Ein Terakawa
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
#include "ssd1306.h"
|
||||
#include "string.h"
|
||||
|
||||
/* timeout value must be increased for i2cclk less than its default, 100kHz. */
|
||||
#define CMD_TRANSMIT_TIMEOUT TIME_MS2I(10)
|
||||
#define DATA_TRANSMIT_TIMEOUT TIME_MS2I(100)
|
||||
|
||||
#define CTRL_CMD_STREAM 0x00
|
||||
#define CTRL_DATA_STREAM 0x40
|
||||
#define CTRL_CMD_SINGLE 0x80
|
||||
|
||||
#define I2CD ((ssd1306)->i2cd)
|
||||
#define ADDR ((ssd1306)->i2caddr)
|
||||
|
||||
#define send_cmd(ssd1306, ...) \
|
||||
do { \
|
||||
uint8_t buf[] = { CTRL_CMD_STREAM, __VA_ARGS__ }; \
|
||||
bool _success = _send_cmd(I2CD, ADDR, buf, sizeof(buf)); \
|
||||
if (!_success) goto done; \
|
||||
} while(0)
|
||||
|
||||
#define send_cmd_static(ssd1306, ...) \
|
||||
do{ \
|
||||
static const uint8_t buf[] = { CTRL_CMD_STREAM, __VA_ARGS__ }; \
|
||||
bool _success = _send_cmd(I2CD, ADDR, buf, sizeof(buf)); \
|
||||
if (!_success) goto done; \
|
||||
} while(0)
|
||||
|
||||
#define CMD1(c) c
|
||||
#define CMD2(c, d) c, d
|
||||
#define CMD3(c, d, e) c, d, e
|
||||
|
||||
static bool _send_cmd(I2CDriver *i2cd, uint8_t addr, const uint8_t *buf, int len) {
|
||||
|
||||
msg_t status = i2cMasterTransmitTimeout(i2cd, addr,
|
||||
buf, len, NULL, 0, CMD_TRANSMIT_TIMEOUT);
|
||||
|
||||
if (MSG_OK != status) {
|
||||
/* i2cflags_t error_code = i2cGetErrors(i2cd); */
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define send_data(ssd1306, buf, len) \
|
||||
do { \
|
||||
bool _success = _send_data(I2CD, ADDR, buf, len); \
|
||||
if (!_success) goto done; \
|
||||
} while(0)
|
||||
|
||||
static bool _send_data(I2CDriver *i2cd, uint8_t addr, const uint8_t *buf, int len) {
|
||||
bool success = false;
|
||||
|
||||
msg_t status = i2cMasterTransmitTimeout(i2cd, addr,
|
||||
buf, len, NULL, 0, DATA_TRANSMIT_TIMEOUT);
|
||||
|
||||
if (MSG_OK != status) {
|
||||
/* i2cflags_t error_code = i2cGetErrors(I2CD); */
|
||||
goto done;
|
||||
}
|
||||
|
||||
success = true;
|
||||
|
||||
done:
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ssd1306_init(SSD1306_DRIVER *ssd1306) {
|
||||
bool success = false;
|
||||
uint8_t width = ssd1306->width;
|
||||
uint8_t height = ssd1306->height;
|
||||
uint8_t num_pages = height / 8;
|
||||
|
||||
i2cStart(I2CD, ssd1306->i2ccfg);
|
||||
|
||||
send_cmd_static(ssd1306,
|
||||
CMD1(SetDisplayOff),
|
||||
CMD1(DeactivateScroll),
|
||||
CMD1(DisableEntireDisplayOn),
|
||||
CMD2(SetOscFreqAndClkDiv, 0x80),
|
||||
CMD2(SetDisplayOffset, 0x00),
|
||||
CMD1(SetDisplayStartLine | 0x00),
|
||||
CMD2(SetMemoryAddressMode, 0x00)); /* Horizontal Addressing Mode */
|
||||
|
||||
send_cmd(ssd1306, CMD2(SetMultiplexRatio, height - 1));
|
||||
|
||||
if (ssd1306->rotate180) {
|
||||
/* rotate 180 degrees == upside down */
|
||||
send_cmd_static(ssd1306,
|
||||
CMD1(SetSegmentRemapReverse),
|
||||
CMD1(SetComScanOrderReverse));
|
||||
} else {
|
||||
/* no rotation */
|
||||
send_cmd_static(ssd1306,
|
||||
CMD1(SetSegmentRemapNormal),
|
||||
CMD1(SetComScanOrderNormal));
|
||||
}
|
||||
|
||||
if (height == 32) {
|
||||
/* 128x32 module uses SequentialComMode */
|
||||
send_cmd_static(ssd1306, CMD2(SetComPins, 0x02));
|
||||
} else {
|
||||
/* 128x64 module uses AlternativeComMode */
|
||||
send_cmd_static(ssd1306, CMD2(SetComPins, 0x12));
|
||||
}
|
||||
|
||||
/* Clear Graphic Display Data RAM */
|
||||
send_cmd(ssd1306,
|
||||
CMD3(SetPageAddress, 0, num_pages - 1),
|
||||
CMD3(SetColumnAddress, 0, width - 1));
|
||||
|
||||
uint8_t *buf = ssd1306->buf;
|
||||
size_t len = SSD1306_PREAMBLE_LENGTH + num_pages * width;
|
||||
memset(buf, 0, len);
|
||||
buf[0] = CTRL_DATA_STREAM; /* need this byte proceeding the actual data */
|
||||
send_data(ssd1306, buf, len);
|
||||
|
||||
send_cmd_static(ssd1306,
|
||||
CMD2(SetPreChargePeriod, 0xC4),
|
||||
CMD2(SetVcomhLevel, 0x20),
|
||||
CMD1(SetNormalDisplay),
|
||||
CMD2(SetContrastControl, 0x3F),
|
||||
CMD2(ChargePumpSetting, 0x14),
|
||||
CMD1(SetDisplayOn));
|
||||
|
||||
success = true;
|
||||
|
||||
done:
|
||||
i2cStop(I2CD);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ssd1306_data(SSD1306_DRIVER *ssd1306) {
|
||||
bool success = false;
|
||||
uint8_t width = ssd1306->width;
|
||||
uint8_t height = ssd1306->height;
|
||||
uint8_t num_pages = height / 8;
|
||||
|
||||
i2cStart(I2CD, ssd1306->i2ccfg);
|
||||
|
||||
/* Transfer to Graphic Display Data RAM */
|
||||
send_cmd(ssd1306,
|
||||
CMD3(SetPageAddress, 0, num_pages - 1),
|
||||
CMD3(SetColumnAddress, 0, width - 1));
|
||||
|
||||
uint8_t *buf = ssd1306->buf;
|
||||
size_t len = SSD1306_PREAMBLE_LENGTH + num_pages * width;
|
||||
send_data(ssd1306, buf, len);
|
||||
|
||||
success = true;
|
||||
|
||||
done:
|
||||
i2cStop(I2CD);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ssd1306_display_on(SSD1306_DRIVER *ssd1306) {
|
||||
bool success = false;
|
||||
i2cStart(I2CD, ssd1306->i2ccfg);
|
||||
send_cmd_static(ssd1306, CMD1(SetDisplayOn));
|
||||
success = true;
|
||||
done:
|
||||
i2cStop(I2CD);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ssd1306_display_off(SSD1306_DRIVER *ssd1306) {
|
||||
bool success = false;
|
||||
i2cStart(I2CD, ssd1306->i2ccfg);
|
||||
send_cmd_static(ssd1306, CMD1(SetDisplayOff));
|
||||
success = true;
|
||||
done:
|
||||
i2cStop(I2CD);
|
||||
return success;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
#ifndef SSD1306_H
|
||||
#define SSD1306_H
|
||||
|
||||
#include <chtypes.h>
|
||||
|
||||
enum ssd1306_cmds {
|
||||
|
||||
/* Fundamental Command */
|
||||
SetContrastControl = 0x81,
|
||||
DisableEntireDisplayOn = 0xA4,
|
||||
EnableEntireDisplayOn = 0xA5,
|
||||
SetNormalDisplay = 0xA6,
|
||||
SetInvertDisplay = 0xA7,
|
||||
SetDisplayOff = 0xAE,
|
||||
SetDisplayOn = 0xAF,
|
||||
|
||||
/* Charge Pump Command */
|
||||
ChargePumpSetting = 0x8D,
|
||||
|
||||
/* Timing & Driving Scheme Setting Command */
|
||||
SetOscFreqAndClkDiv = 0xD5,
|
||||
SetPreChargePeriod = 0xD9,
|
||||
SetVcomhLevel = 0xDB,
|
||||
|
||||
/* Addressing Setting Command */
|
||||
SetMemoryAddressMode = 0x20,
|
||||
SetColumnAddress = 0x21,
|
||||
SetPageAddress = 0x22,
|
||||
// SetLowColumn = 0x00, /* 0x00 - 0x0F */
|
||||
// SetHighColumn = 0x10, /* 0x10 - 0x1F */
|
||||
// SetPageStartAddress = 0xB0, /* 0xB0 - 0xB7 */
|
||||
|
||||
/* Hardware Configuration Command */
|
||||
SetDisplayStartLine = 0x40, /* 0x40 - 0x7F */
|
||||
SetSegmentRemapNormal = 0xA0,
|
||||
SetSegmentRemapReverse = 0xA1,
|
||||
SetMultiplexRatio = 0xA8,
|
||||
SetComScanOrderNormal = 0xC0,
|
||||
SetComScanOrderReverse = 0xC8,
|
||||
SetDisplayOffset = 0xD3,
|
||||
SetComPins = 0xDA,
|
||||
|
||||
/* Scrolling Command */
|
||||
RightHorizontalScroll = 0x26,
|
||||
LeftHorizontalScroll = 0x27,
|
||||
VerticalAndRightHorizontalScroll = 0x29,
|
||||
VerticalAndLeftHorizontalScroll = 0x2A,
|
||||
DeactivateScroll = 0x2E,
|
||||
ActivateScroll = 0x2F,
|
||||
SetVerticalScrollArea = 0xA3,
|
||||
|
||||
/* Other Command */
|
||||
NoOperation = 0xE3,
|
||||
};
|
||||
|
||||
#ifndef SSD1306_ADDRESS
|
||||
/* for your reference (0x3C << 1) == 0x78 , (0x3D << 1) == 0x7A . */
|
||||
#define SSD1306_ADDRESS 0x3C
|
||||
#endif
|
||||
|
||||
typedef struct I2CDriver I2CDriver;
|
||||
typedef struct I2CConfig I2CConfig;
|
||||
typedef struct SSD1306_DRIVER {
|
||||
I2CDriver *i2cd;
|
||||
I2CConfig const *i2ccfg;
|
||||
uint8_t i2caddr;
|
||||
uint8_t width;
|
||||
uint8_t height;
|
||||
bool rotate180;
|
||||
uint8_t *buf;
|
||||
} SSD1306_DRIVER;
|
||||
|
||||
#define SSD1306_PREAMBLE_LENGTH 1
|
||||
#define DEFINE_SSD1306_DRIVER(name, i2cd, addr, width, height, rotate180) \
|
||||
_Static_assert(width == 128, "Only support width of 128 for simplicity."); \
|
||||
_Static_assert(height == 32 || height == 64, "Only support height of 32 or 64 for simplicity."); \
|
||||
uint8_t name##_buf[SSD1306_PREAMBLE_LENGTH + width * height / 8]; \
|
||||
struct SSD1306_DRIVER name = { \
|
||||
i2cd, NULL, addr, width, height, rotate180, name##_buf \
|
||||
}
|
||||
|
||||
#define SSD1306_GET_FRAMEBUFFER(ssd1306) \
|
||||
(&((ssd1306)->buf[SSD1306_PREAMBLE_LENGTH]))
|
||||
|
||||
bool ssd1306_init(SSD1306_DRIVER *ssd1306);
|
||||
bool ssd1306_data(SSD1306_DRIVER *ssd1306);
|
||||
bool ssd1306_display_on(SSD1306_DRIVER *ssd1306);
|
||||
bool ssd1306_display_off(SSD1306_DRIVER *ssd1306);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue