mirror of https://github.com/ARMmbed/mbed-os.git
Added new features to TMPM46B
parent
033fffea84
commit
edf36fb2ae
|
@ -244,8 +244,6 @@ FunctionalState ESG_GetIntStatus(void)
|
|||
*/
|
||||
void ESG_IPReset(void)
|
||||
{
|
||||
uint32_t iprst3 = 0U;
|
||||
|
||||
/* Disable write protection state of SRSTIPRST */
|
||||
TSB_SRST->PROTECT = SRST_PROTECT_DISABLE;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef MBED_DEVICE_H
|
||||
#define MBED_DEVICE_H
|
||||
|
||||
#define TRANSACTION_QUEUE_SIZE_SPI 4
|
||||
#define DEVICE_ID_LENGTH 32
|
||||
|
||||
#include "objects.h"
|
||||
|
|
|
@ -45,6 +45,6 @@ LR_IROM1 MBED_APP_START MBED_APP_SIZE ; load region size_region
|
|||
.ANY (+RW, +ZI)
|
||||
}
|
||||
|
||||
ARM_LIB_STACK (0x200001E0+0x80000) EMPTY -Stack_Size { ; stack
|
||||
ARM_LIB_STACK (0x20000000+0x80000) EMPTY -Stack_Size { ; stack
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,13 +317,11 @@ void SystemInit(void)
|
|||
volatile uint32_t oscf = 0U;
|
||||
uint32_t wdte = 0U;
|
||||
|
||||
#if defined ( __CC_ARM )/*Enable FPU for Keil*/
|
||||
#if (__FPU_USED == 1) /* __FPU_USED is defined in core_cm4.h */
|
||||
/* enable FPU if available and used */
|
||||
SCB->CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */
|
||||
(3UL << 11*2) ); /* set CP11 Full Access */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (WD_SETUP) /* Watchdog Setup */
|
||||
while (TSB_WD->FLG != 0U) {
|
||||
|
|
|
@ -18,11 +18,11 @@
|
|||
#include "mbed_critical.h"
|
||||
#include "tmpm46b_fc.h"
|
||||
|
||||
#define PROGRAM_WIRTE_MAX 16U /* Page program could be written 16 bytes/4 words once */
|
||||
#define SECTOR_SIZE 0x8000 /* (512 * 8) sectors */
|
||||
#define PAGE_SIZE 16U /* Page program size is 16 bytes */
|
||||
#define PROGRAM_WIRTE_MAX 16U // Page program could be written 16 bytes/4 words once
|
||||
#define SECTOR_SIZE 0x8000 // (512 * 8) sectors
|
||||
#define PAGE_SIZE 16U // Page program size is 16 bytes
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#define FLASH_API_ROM ((uint32_t *)__section_begin("FLASH_CODE_ROM"))
|
||||
#define SIZE_FLASH_API ((uint32_t)__section_size("FLASH_CODE_ROM"))
|
||||
#define FLASH_API_RAM ((uint32_t *)__section_begin("FLASH_CODE_RAM"))
|
||||
|
@ -30,7 +30,7 @@
|
|||
#pragma section = "FLASH_CODE_ROM"
|
||||
#endif
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
static void Copy_Routine(uint32_t *dest, uint32_t *source, uint32_t size)
|
||||
{
|
||||
uint32_t *dest_addr, *source_addr, tmpsize;
|
||||
|
@ -40,12 +40,12 @@ static void Copy_Routine(uint32_t * dest, uint32_t * source, uint32_t size)
|
|||
source_addr = source;
|
||||
|
||||
tmpsize = size >> 2U;
|
||||
for (i = 0U; i < tmpsize; i++) { /* 32bits copy */
|
||||
for (i = 0U; i < tmpsize; i++) { // 32bits copy
|
||||
*dest_addr = *source_addr;
|
||||
dest_addr++;
|
||||
source_addr++;
|
||||
}
|
||||
if (size & 0x00000003U) { /* if the last data size is not 0(maybe 1,2 or 3), copy the last data */
|
||||
if (size & 0x00000003U) { // if the last data size is not 0(maybe 1,2 or 3), copy the last data
|
||||
mask = 0xFFFFFF00U;
|
||||
i = size & 0x00000003U;
|
||||
tmps = *source_addr;
|
||||
|
@ -56,9 +56,9 @@ static void Copy_Routine(uint32_t * dest, uint32_t * source, uint32_t size)
|
|||
}
|
||||
tmps = tmps & (~mask);
|
||||
tmpd = tmpd & (mask);
|
||||
*dest_addr = tmps + tmpd; /* 32bits copy, but only change the bytes need to be changed */
|
||||
*dest_addr = tmps + tmpd; // 32bits copy, but only change the bytes need to be changed
|
||||
} else {
|
||||
/* Do nothing */
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -69,7 +69,7 @@ int32_t flash_init(flash_t *obj)
|
|||
TSB_FC->PROGCR = 0x00000001U;
|
||||
TSB_FC->ERASECR = 0x00000007U;
|
||||
TSB_FC->AREASEL = 0x00000000U;
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
Copy_Routine(FLASH_API_RAM, FLASH_API_ROM, SIZE_FLASH_API);
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -80,36 +80,36 @@ int32_t flash_free(flash_t *obj)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
int32_t flash_erase_sector(flash_t *obj, uint32_t address)
|
||||
{
|
||||
int status = FAIL;
|
||||
/* We need to prevent flash accesses during erase operation */
|
||||
// We need to prevent flash accesses during erase operation
|
||||
core_util_critical_section_enter();
|
||||
|
||||
if (FC_SUCCESS == FC_EraseBlock(address)) {
|
||||
status = SUCCESS;
|
||||
} else {
|
||||
/* Do nothing */
|
||||
// Do nothing
|
||||
}
|
||||
core_util_critical_section_exit();
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size)
|
||||
{
|
||||
int status = SUCCESS;
|
||||
|
||||
/* We need to prevent flash accesses during program operation */
|
||||
// We need to prevent flash accesses during program operation
|
||||
core_util_critical_section_enter();
|
||||
while (size > PROGRAM_WIRTE_MAX) {
|
||||
if (FC_SUCCESS == FC_WritePage((uint32_t)address, (uint32_t *)data)) { /* write one page every time */
|
||||
/* Do nothing */
|
||||
if (FC_SUCCESS == FC_WritePage((uint32_t)address, (uint32_t *)data)) { // write one page every time
|
||||
// Do nothing
|
||||
} else {
|
||||
status = FAIL;
|
||||
break;
|
||||
|
@ -118,8 +118,8 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
|
|||
address = address + PROGRAM_WIRTE_MAX;
|
||||
data = data + PROGRAM_WIRTE_MAX;
|
||||
}
|
||||
if (FC_SUCCESS == FC_WritePage((uint32_t)address, (uint32_t *)data)) { /* write the last data, no more than one page */
|
||||
/* Do nothing */
|
||||
if (FC_SUCCESS == FC_WritePage((uint32_t)address, (uint32_t *)data)) { // write the last data, no more than one page
|
||||
// Do nothing
|
||||
} else {
|
||||
status = FAIL;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data,
|
|||
return status;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
|
||||
|
@ -139,7 +139,7 @@ uint32_t flash_get_sector_size(const flash_t *obj, uint32_t address)
|
|||
return SECTOR_SIZE;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
uint32_t flash_get_page_size(const flash_t *obj)
|
||||
|
@ -147,7 +147,7 @@ uint32_t flash_get_page_size(const flash_t *obj)
|
|||
return PAGE_SIZE;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
uint32_t flash_get_start_address(const flash_t *obj)
|
||||
|
@ -155,7 +155,7 @@ uint32_t flash_get_start_address(const flash_t *obj)
|
|||
return FLASH_START_ADDR;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
uint32_t flash_get_size(const flash_t *obj)
|
||||
|
@ -163,7 +163,7 @@ uint32_t flash_get_size(const flash_t *obj)
|
|||
return FLASH_CHIP_SIZE;
|
||||
}
|
||||
|
||||
#if defined ( __ICCARM__ ) /* IAR Compiler */
|
||||
#if defined ( __ICCARM__ ) // IAR Compiler
|
||||
#pragma location = "FLASH_ROM"
|
||||
#endif
|
||||
uint8_t flash_get_erase_value(const flash_t *obj)
|
||||
|
@ -172,4 +172,3 @@ uint8_t flash_get_erase_value(const flash_t *obj)
|
|||
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,35 @@
|
|||
#include "PeripheralNames.h"
|
||||
#include "pinmap.h"
|
||||
#include "tmpm46b_i2c.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SBI_I2C_SEND 0x00
|
||||
#define SBI_I2C_RECEIVE 0x01
|
||||
#define I2C_TRANSFER_STATE_IDLE (0x0U)
|
||||
#define I2C_TRANSFER_STATE_BUSY (0x1U)
|
||||
#define I2C_ACK (1)
|
||||
#define I2C_NO_DATA (0)
|
||||
#define I2C_READ_ADDRESSED (1)
|
||||
#define I2C_WRITE_ADDRESSED (3)
|
||||
#define I2C_TIMEOUT (100000)
|
||||
#define I2CCR2_REPEATED_START_CONDITION ((uint32_t)0x00000018)
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
#define I2C_S(obj) (struct i2c_s *) (&(obj->i2c))
|
||||
#else
|
||||
#define I2C_S(obj) (struct i2c_s *) (obj)
|
||||
#endif
|
||||
|
||||
static inline void repeated_start(struct i2c_s *obj_s);
|
||||
static int32_t wait_status(i2c_t *obj);
|
||||
static void I2C_Start_Condition(struct i2c_s *p_obj, uint32_t data);
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
static inline void state_idle(struct i2c_s *obj_s);
|
||||
#endif
|
||||
|
||||
static const PinMap PinMap_I2C_SDA[] = {
|
||||
{PK2, I2C_0, PIN_DATA(3, 2)},
|
||||
{PF7, I2C_1, PIN_DATA(4, 2)},
|
||||
|
@ -38,47 +64,25 @@ static const PinMap PinMap_I2C_SCL[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
#define SBI_I2C_SEND 0x00
|
||||
#define SBI_I2C_RECEIVE 0x01
|
||||
#define MAX_NUM_I2C 3
|
||||
#define DELAY_MS_MULTIPLIER 5500
|
||||
|
||||
struct i2c_xfer {
|
||||
int32_t count;
|
||||
int32_t len;
|
||||
void *done;
|
||||
char *buf;
|
||||
};
|
||||
|
||||
// Clock setting structure definition
|
||||
typedef struct {
|
||||
uint32_t sck;
|
||||
uint32_t prsck;
|
||||
} I2C_clock_setting_t;
|
||||
|
||||
static void DelayMS(uint32_t delay)
|
||||
{
|
||||
volatile uint32_t VarI;
|
||||
for (VarI = 0; VarI < delay * DELAY_MS_MULTIPLIER; VarI++);
|
||||
}
|
||||
|
||||
static const uint32_t I2C_SCK_DIVIDER_TBL[8] = {
|
||||
20, 24, 32, 48, 80, 144, 272, 528
|
||||
}; // SCK Divider value table
|
||||
|
||||
static int32_t start_flag = 0;
|
||||
static I2C_State status;
|
||||
static I2C_clock_setting_t clk;
|
||||
static I2C_InitTypeDef myi2c;
|
||||
static int32_t start_flag = 1;
|
||||
static struct i2c_xfer xfer[MAX_NUM_I2C];
|
||||
static TSB_I2C_TypeDef *i2c_lut[MAX_NUM_I2C] = {TSB_I2C0, TSB_I2C1, TSB_I2C2};
|
||||
static char *gI2C_TxData = NULL;
|
||||
static char *gI2C_LTxData = NULL;
|
||||
static uint8_t send_byte = 0;
|
||||
static uint8_t byte_func = 0;
|
||||
|
||||
// Initialize the I2C peripheral. It sets the default parameters for I2C
|
||||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
MBED_ASSERT(obj != NULL);
|
||||
I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
|
||||
I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
|
||||
|
@ -89,29 +93,32 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
|||
case I2C_0:
|
||||
CG_SetFcPeriphB(CG_FC_PERIPH_I2C0, ENABLE);
|
||||
CG_SetFcPeriphA(CG_FC_PERIPH_PORTK, ENABLE);
|
||||
obj->i2c = TSB_I2C0;
|
||||
obj->index = 0;
|
||||
obj->IRQn = INTI2C0_IRQn;
|
||||
obj_s->i2c = TSB_I2C0;
|
||||
obj_s->index = 0;
|
||||
obj_s->IRQn = INTI2C0_IRQn;
|
||||
break;
|
||||
case I2C_1:
|
||||
CG_SetFcPeriphB(CG_FC_PERIPH_I2C1, ENABLE);
|
||||
CG_SetFcPeriphA(CG_FC_PERIPH_PORTF, ENABLE);
|
||||
obj->i2c = TSB_I2C1;
|
||||
obj->index = 1;
|
||||
obj->IRQn = INTI2C1_IRQn;
|
||||
obj_s->i2c = TSB_I2C1;
|
||||
obj_s->index = 1;
|
||||
obj_s->IRQn = INTI2C1_IRQn;
|
||||
break;
|
||||
case I2C_2:
|
||||
CG_SetFcPeriphB(CG_FC_PERIPH_I2C2, ENABLE);
|
||||
CG_SetFcPeriphA(CG_FC_PERIPH_PORTH, ENABLE);
|
||||
obj->i2c = TSB_I2C2;
|
||||
obj->index = 2;
|
||||
obj->IRQn = INTI2C2_IRQn;
|
||||
obj_s->i2c = TSB_I2C2;
|
||||
obj_s->index = 2;
|
||||
obj_s->IRQn = INTI2C2_IRQn;
|
||||
break;
|
||||
default:
|
||||
error("I2C is not available");
|
||||
break;
|
||||
}
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
obj_s->state = I2C_TRANSFER_STATE_IDLE;
|
||||
#endif
|
||||
pinmap_pinout(sda, PinMap_I2C_SDA);
|
||||
pin_mode(sda, OpenDrain);
|
||||
pin_mode(sda, PullUp);
|
||||
|
@ -120,6 +127,7 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
|||
pin_mode(scl, OpenDrain);
|
||||
pin_mode(scl, PullUp);
|
||||
|
||||
NVIC_DisableIRQ(obj_s->IRQn);
|
||||
i2c_reset(obj);
|
||||
i2c_frequency(obj, 100000);
|
||||
}
|
||||
|
@ -127,13 +135,14 @@ void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
|||
// Configure the I2C frequency
|
||||
void i2c_frequency(i2c_t *obj, int hz)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
uint32_t sck = 0;
|
||||
uint32_t tmp_sck = 0;
|
||||
uint32_t prsck = 1;
|
||||
uint32_t tmp_prsck = 1;
|
||||
uint32_t fscl = 0;
|
||||
uint32_t tmp_fscl = 0;
|
||||
uint64_t fx;
|
||||
uint64_t fx = 0;
|
||||
|
||||
if (hz <= 400000) { // Maximum 400khz clock frequency supported by M46B
|
||||
for (prsck = 1; prsck <= 32; prsck++) {
|
||||
|
@ -161,10 +170,9 @@ void i2c_frequency(i2c_t *obj, int hz)
|
|||
myi2c.I2CClkDiv = clk.sck;
|
||||
myi2c.PrescalerClkDiv = clk.prsck;
|
||||
|
||||
I2C_SWReset(obj->i2c);
|
||||
I2C_Init(obj->i2c, &myi2c);
|
||||
NVIC_EnableIRQ(obj->IRQn);
|
||||
I2C_SetINTReq(obj->i2c, ENABLE);
|
||||
I2C_SWReset(obj_s->i2c);
|
||||
I2C_Init(obj_s->i2c, &myi2c);
|
||||
NVIC_DisableIRQ(obj_s->IRQn);
|
||||
}
|
||||
|
||||
int i2c_start(i2c_t *obj)
|
||||
|
@ -175,187 +183,389 @@ int i2c_start(i2c_t *obj)
|
|||
|
||||
int i2c_stop(i2c_t *obj)
|
||||
{
|
||||
I2C_GenerateStop(obj->i2c);
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i2c_reset(i2c_t *obj)
|
||||
{
|
||||
I2C_SWReset(obj->i2c);
|
||||
}
|
||||
|
||||
static void wait_i2c_bus_free(i2c_t *obj)
|
||||
{
|
||||
I2C_State status;
|
||||
|
||||
do {
|
||||
status = I2C_GetState(obj->i2c);
|
||||
} while (status.Bit.BusState);
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
I2C_SWReset(obj_s->i2c);
|
||||
}
|
||||
|
||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||
{
|
||||
TSB_I2C_TypeDef *sbi = obj->i2c;
|
||||
uint32_t i2c_num = 0;
|
||||
obj->address = address;
|
||||
int32_t result = 0;
|
||||
int32_t count = 0;
|
||||
|
||||
i2c_num = obj->index;
|
||||
if (length > 0) {
|
||||
start_flag = 1; // Start Condition
|
||||
if (i2c_byte_write(obj, (int32_t)((uint32_t)address | 1U)) == I2C_ACK) {
|
||||
while (count < length) {
|
||||
int32_t pdata = i2c_byte_read(obj, ((count < (length - 1)) ? 0 : 1));
|
||||
if (pdata < 0) {
|
||||
break;
|
||||
}
|
||||
data[count++] = (uint8_t)pdata;
|
||||
}
|
||||
result = count;
|
||||
} else {
|
||||
stop = 1;
|
||||
result = I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
||||
// receive data
|
||||
xfer[i2c_num].count = 0;
|
||||
xfer[i2c_num].len = length;
|
||||
xfer[i2c_num].buf = data;
|
||||
|
||||
I2C_SetSendData(sbi, address | SBI_I2C_RECEIVE);
|
||||
I2C_GenerateStart(sbi);
|
||||
|
||||
wait_i2c_bus_free(obj);
|
||||
return (xfer[i2c_num].count - 1);
|
||||
if (stop) { // Stop Condition
|
||||
i2c_stop(obj);
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||
{
|
||||
int8_t i = 0;
|
||||
TSB_I2C_TypeDef *sbi = obj->i2c;
|
||||
uint32_t i2c_num = 0;
|
||||
obj->address = address;
|
||||
int32_t result = 0;
|
||||
int32_t count = 0;
|
||||
|
||||
i2c_num = obj->index;
|
||||
gI2C_TxData = (char *)calloc(length, sizeof(int8_t));
|
||||
if (gI2C_TxData == NULL) {
|
||||
error("Insufficient memory");
|
||||
return 0;
|
||||
start_flag = 1; // Start Condition
|
||||
if (i2c_byte_write(obj, address) == I2C_ACK) {
|
||||
while (count < length) {
|
||||
if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = count;
|
||||
} else {
|
||||
stop = 1;
|
||||
result = I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
gI2C_TxData[i] = data[i];
|
||||
if (stop) { // Stop Condition
|
||||
i2c_stop(obj);
|
||||
}
|
||||
// receive data
|
||||
xfer[i2c_num].count = 0;
|
||||
xfer[i2c_num].len = length;
|
||||
xfer[i2c_num].buf = gI2C_TxData;
|
||||
|
||||
I2C_SetSendData(sbi, address | SBI_I2C_SEND);
|
||||
I2C_GenerateStart(sbi); // Start condition
|
||||
|
||||
wait_i2c_bus_free(obj);
|
||||
free(gI2C_TxData);
|
||||
DelayMS(8);
|
||||
if (((xfer[i2c_num].count - 1) == 0) && (byte_func == 1)) {
|
||||
send_byte = 1;
|
||||
i2c_byte_write(obj, 0x00);
|
||||
xfer[i2c_num].count = 1;
|
||||
byte_func = 0;
|
||||
}
|
||||
return (xfer[i2c_num].count - 1);
|
||||
return (result);
|
||||
}
|
||||
|
||||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
char i2c_ret = 0;
|
||||
i2c_read(obj, obj->address, &i2c_ret, 1, last);
|
||||
return i2c_ret;
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
|
||||
int32_t result;
|
||||
|
||||
I2C_ClearINTOutput(obj_s->i2c);
|
||||
|
||||
if (last) {
|
||||
I2C_SetACK(obj_s->i2c, DISABLE);
|
||||
} else {
|
||||
I2C_SetACK(obj_s->i2c, ENABLE);
|
||||
}
|
||||
I2C_SetSendData(obj_s->i2c, 0x00);
|
||||
|
||||
if (wait_status(obj) < 0) {
|
||||
result = -1;
|
||||
} else {
|
||||
result = (int32_t)I2C_GetReceiveData(obj_s->i2c);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
uint32_t wb = 1;
|
||||
static size_t counter = 1;
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
|
||||
byte_func = 1;
|
||||
if (start_flag == 0 && send_byte == 0) {
|
||||
gI2C_LTxData = (char *)realloc(gI2C_LTxData, counter++);
|
||||
if (gI2C_LTxData == NULL) {
|
||||
error("Insufficient memory");
|
||||
return 0;
|
||||
}
|
||||
gI2C_LTxData[counter - 2] = data;
|
||||
}
|
||||
int32_t result;
|
||||
|
||||
I2C_ClearINTOutput(obj_s->i2c);
|
||||
|
||||
if (send_byte == 1) {
|
||||
wb = i2c_write(obj, obj->address, gI2C_LTxData, (counter - 1), 0);
|
||||
start_flag = 1;
|
||||
send_byte = 0;
|
||||
byte_func = 0;
|
||||
counter = 1;
|
||||
return wb;
|
||||
} else {
|
||||
if (start_flag == 1) {
|
||||
obj->address = data;
|
||||
I2C_Start_Condition(obj_s, (uint32_t)data);
|
||||
start_flag = 0;
|
||||
} else {
|
||||
// Store the number of written bytes
|
||||
wb = i2c_write(obj, obj->address, (char*)&data, 1, 0);
|
||||
}
|
||||
if (wb == 1)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
I2C_SetSendData(obj_s->i2c, (uint32_t)data);
|
||||
}
|
||||
|
||||
static void i2c_irq_handler(int i2c_num)
|
||||
if (wait_status(obj) < 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
status = I2C_GetState(obj_s->i2c);
|
||||
if (!status.Bit.LastRxBit) {
|
||||
result = 1;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
void i2c_slave_mode(i2c_t *obj, int enable_slave)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
TSB_I2C_TypeDef *sbi = i2c_lut[i2c_num];
|
||||
I2C_State sbi_sr;
|
||||
i2c_reset(obj);
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
|
||||
sbi_sr = I2C_GetState(sbi);
|
||||
obj_s->myi2c.I2CDataLen = I2C_DATA_LEN_8;
|
||||
obj_s->myi2c.I2CACKState = ENABLE;
|
||||
obj_s->myi2c.I2CClkDiv = clk.sck;
|
||||
obj_s->myi2c.PrescalerClkDiv = clk.prsck;
|
||||
|
||||
// we don't support slave mode
|
||||
if (!sbi_sr.Bit.MasterSlave)
|
||||
return;
|
||||
if (enable_slave) {
|
||||
obj_s->myi2c.I2CSelfAddr = obj_s->address;
|
||||
I2C_SetINTReq(obj_s->i2c, ENABLE);
|
||||
} else {
|
||||
obj_s->myi2c.I2CSelfAddr = 0xE0;
|
||||
NVIC_DisableIRQ(obj_s->IRQn);
|
||||
I2C_ClearINTOutput(obj_s->i2c);
|
||||
}
|
||||
I2C_Init(obj_s->i2c, &obj_s->myi2c);
|
||||
}
|
||||
|
||||
int i2c_slave_receive(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
int32_t result = I2C_NO_DATA;
|
||||
|
||||
if ((I2C_GetINTStatus(obj_s->i2c)) && (I2C_GetSlaveAddrMatchState(obj_s->i2c))) {
|
||||
status = I2C_GetState(obj_s->i2c);
|
||||
if (!status.Bit.TRx) {
|
||||
result = I2C_WRITE_ADDRESSED;
|
||||
} else {
|
||||
result = I2C_READ_ADDRESSED;
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
int i2c_slave_read(i2c_t *obj, char *data, int length)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
int32_t count = 0;
|
||||
|
||||
while (count < length) {
|
||||
int32_t pdata = i2c_byte_read(obj, 0);
|
||||
status = I2C_GetState(obj_s->i2c);
|
||||
if (status.Bit.TRx) {
|
||||
return (count);
|
||||
} else {
|
||||
if (pdata < 0) {
|
||||
break;
|
||||
}
|
||||
data[count++] = (uint8_t)pdata;
|
||||
}
|
||||
}
|
||||
i2c_slave_mode(obj, 1);
|
||||
return (count);
|
||||
}
|
||||
|
||||
int i2c_slave_write(i2c_t *obj, const char *data, int length)
|
||||
{
|
||||
int32_t count = 0;
|
||||
|
||||
while (count < length) {
|
||||
if (i2c_byte_write(obj, (int32_t)data[count++]) < I2C_ACK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
i2c_slave_mode(obj, 1);
|
||||
return (count);
|
||||
}
|
||||
|
||||
void i2c_slave_address(i2c_t *obj, int idx, uint32_t address, uint32_t mask)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
obj_s->address = address & 0xFE;
|
||||
i2c_slave_mode(obj, 1);
|
||||
}
|
||||
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address,
|
||||
uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
obj_s->event_mask = event;
|
||||
obj_s->stop = stop;
|
||||
obj_s->address = address;
|
||||
|
||||
// copy the buffers to the I2C object
|
||||
obj->tx_buff.buffer = (void *) tx;
|
||||
obj->tx_buff.length = tx ? tx_length : 0;
|
||||
obj->tx_buff.pos = 0;
|
||||
|
||||
obj->rx_buff.buffer = rx;
|
||||
obj->rx_buff.length = rx ? rx_length : 0;
|
||||
obj->rx_buff.pos = 0;
|
||||
|
||||
obj_s->state = I2C_TRANSFER_STATE_BUSY;
|
||||
I2C_SetINTReq(obj_s->i2c, ENABLE);
|
||||
NVIC_ClearPendingIRQ(obj_s->IRQn);
|
||||
NVIC_SetVector(obj_s->IRQn, (uint32_t)handler);
|
||||
NVIC_EnableIRQ(obj_s->IRQn);
|
||||
|
||||
if ((tx_length == 0) && (rx_length != 0)) {
|
||||
I2C_SetSendData(obj_s->i2c, address | SBI_I2C_RECEIVE);
|
||||
} else {
|
||||
I2C_SetSendData(obj_s->i2c, address | SBI_I2C_SEND);
|
||||
}
|
||||
I2C_GenerateStart(obj_s->i2c);
|
||||
}
|
||||
|
||||
uint32_t i2c_irq_handler_asynch(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
uint32_t tmp_read = 0U;
|
||||
uint32_t event = 0;
|
||||
I2C_State flag_state;
|
||||
|
||||
flag_state = I2C_GetState(obj_s->i2c);
|
||||
|
||||
if ((!flag_state.Bit.MasterSlave) || (obj_s->state != I2C_TRANSFER_STATE_BUSY)) {
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
event = I2C_EVENT_ERROR;
|
||||
state_idle(obj_s);
|
||||
return (event & obj_s->event_mask);
|
||||
}
|
||||
|
||||
if (flag_state.Bit.TRx) { // Transmit
|
||||
|
||||
if (flag_state.Bit.LastRxBit) { // NACK Recieved
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
|
||||
if (obj->tx_buff.pos == 0) {
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
event = (I2C_EVENT_ERROR | I2C_EVENT_ERROR_NO_SLAVE);
|
||||
state_idle(obj_s);
|
||||
|
||||
} else {
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
event = (I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK);
|
||||
state_idle(obj_s);
|
||||
}
|
||||
|
||||
} else { // ACK Received
|
||||
|
||||
if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||
I2C_SetSendData(obj_s->i2c, (*((uint8_t *)obj->tx_buff.buffer + obj->tx_buff.pos) & 0xFF)); // Send next data
|
||||
obj->tx_buff.pos++;
|
||||
|
||||
} else if (obj->rx_buff.length != 0) { // Transmit complete Receive Pending
|
||||
repeated_start(obj_s);
|
||||
I2C_SetSendData(obj_s->i2c, obj_s->address | SBI_I2C_RECEIVE);
|
||||
|
||||
} else { // Transmit complete and NO data to Receive
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
event = I2C_EVENT_TRANSFER_COMPLETE;
|
||||
state_idle(obj_s);
|
||||
}
|
||||
}
|
||||
} else { // Receive
|
||||
|
||||
if (obj->rx_buff.pos > obj->rx_buff.length) {
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
event = I2C_EVENT_TRANSFER_COMPLETE;
|
||||
state_idle(obj_s);
|
||||
I2C_SetACK(obj_s->i2c, ENABLE);
|
||||
|
||||
} else {
|
||||
|
||||
if (obj->rx_buff.pos == obj->rx_buff.length) {
|
||||
I2C_SetBitNum(obj_s->i2c, I2C_DATA_LEN_1);
|
||||
|
||||
} else if (obj->rx_buff.pos == (obj->rx_buff.length - 1)) {
|
||||
I2C_SetACK(obj_s->i2c, DISABLE);
|
||||
|
||||
if (sbi_sr.Bit.TRx) { // Tx mode
|
||||
if (sbi_sr.Bit.LastRxBit) { // LRB=1: the receiver requires no further data.
|
||||
I2C_GenerateStop(sbi);
|
||||
} else { // LRB=0: the receiver requires further data.
|
||||
if (xfer[i2c_num].count < xfer[i2c_num].len) {
|
||||
I2C_SetSendData(sbi, xfer[i2c_num].buf[xfer[i2c_num].count]); // Send next data
|
||||
} else if (xfer[i2c_num].count == xfer[i2c_num].len) { // I2C data send finished.
|
||||
I2C_GenerateStop(sbi);
|
||||
} else {
|
||||
// Do nothing
|
||||
}
|
||||
xfer[i2c_num].count++;
|
||||
}
|
||||
} else { // Rx Mode
|
||||
if (xfer[i2c_num].count > xfer[i2c_num].len) {
|
||||
I2C_GenerateStop(sbi);
|
||||
I2C_SetACK(sbi, ENABLE);
|
||||
} else {
|
||||
if (xfer[i2c_num].count == xfer[i2c_num].len) { // Rx last data
|
||||
I2C_SetBitNum(sbi, I2C_DATA_LEN_1);
|
||||
} else if (xfer[i2c_num].count == (xfer[i2c_num].len - 1)) { // Rx the data second to last
|
||||
// Not generate ACK for next data Rx end.
|
||||
I2C_SetACK(sbi, DISABLE);
|
||||
} else {
|
||||
// Do nothing
|
||||
}
|
||||
tmp = I2C_GetReceiveData(sbi);
|
||||
if (xfer[i2c_num].count > 0) {
|
||||
xfer[i2c_num].buf[xfer[i2c_num].count - 1U] = tmp;
|
||||
|
||||
tmp_read = I2C_GetReceiveData(obj_s->i2c);
|
||||
|
||||
if (obj->rx_buff.pos > 0) {
|
||||
*((uint8_t *)obj->rx_buff.buffer + (obj->rx_buff.pos - 1)) = tmp_read;
|
||||
} else {
|
||||
// first read is dummy read
|
||||
}
|
||||
xfer[i2c_num].count++;
|
||||
}
|
||||
obj->rx_buff.pos++;
|
||||
}
|
||||
}
|
||||
|
||||
void INTI2C0_IRQHandler(void)
|
||||
{
|
||||
i2c_irq_handler(0);
|
||||
return (event & obj_s->event_mask);
|
||||
}
|
||||
|
||||
void INTI2C1_IRQHandler(void)
|
||||
uint8_t i2c_active(i2c_t *obj)
|
||||
{
|
||||
i2c_irq_handler(1);
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
|
||||
return (obj_s->state != I2C_TRANSFER_STATE_IDLE);
|
||||
}
|
||||
|
||||
void INTI2C2_IRQHandler(void)
|
||||
void i2c_abort_asynch(i2c_t *obj)
|
||||
{
|
||||
i2c_irq_handler(2);
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
|
||||
I2C_ClearINTReq(obj_s->i2c);
|
||||
NVIC_ClearPendingIRQ(obj_s->IRQn);
|
||||
I2C_GenerateStop(obj_s->i2c);
|
||||
state_idle(obj_s);
|
||||
I2C_SWReset(obj_s->i2c);
|
||||
I2C_Init(obj_s->i2c, &obj_s->myi2c);
|
||||
}
|
||||
|
||||
static inline void state_idle(struct i2c_s *obj_s)
|
||||
{
|
||||
I2C_State flag_state;
|
||||
|
||||
obj_s->state = I2C_TRANSFER_STATE_IDLE;
|
||||
NVIC_DisableIRQ(obj_s->IRQn);
|
||||
I2C_SetINTReq(obj_s->i2c, DISABLE);
|
||||
// wait until bus state releases after stop condition
|
||||
do {
|
||||
flag_state = I2C_GetState(obj_s->i2c);
|
||||
} while (flag_state.Bit.BusState);
|
||||
// To satisfy the setup time of restart, at least 4.7µs wait must be created by software (Ref. TRM pg. 561)
|
||||
wait_us(5);
|
||||
}
|
||||
|
||||
#endif //DEVICE_I2C_ASYNCH
|
||||
|
||||
static int32_t wait_status(i2c_t *obj)
|
||||
{
|
||||
struct i2c_s *obj_s = I2C_S(obj);
|
||||
volatile int32_t timeout = I2C_TIMEOUT;
|
||||
|
||||
while (I2C_GetINTStatus(obj_s->i2c) == DISABLE) {
|
||||
if ((timeout--) == 0) {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline void repeated_start(struct i2c_s *obj_s)
|
||||
{
|
||||
I2C_State flag_state;
|
||||
|
||||
obj_s->i2c->CR2 = I2CCR2_REPEATED_START_CONDITION;
|
||||
// wait until bus state releases
|
||||
do {
|
||||
flag_state = I2C_GetState(obj_s->i2c);
|
||||
} while (flag_state.Bit.BusState);
|
||||
// Checks that no other device is pulling the SCL pin to "Low".
|
||||
do {
|
||||
flag_state = I2C_GetState(obj_s->i2c);
|
||||
} while (!flag_state.Bit.LastRxBit);
|
||||
|
||||
I2C_GenerateStart(obj_s->i2c);
|
||||
}
|
||||
|
||||
static void I2C_Start_Condition(struct i2c_s *p_obj, uint32_t data)
|
||||
{
|
||||
status = I2C_GetState(p_obj->i2c);
|
||||
if (status.Bit.BusState) {
|
||||
repeated_start(p_obj);
|
||||
I2C_SetSendData(p_obj->i2c, (uint32_t)data);
|
||||
} else {
|
||||
I2C_SetSendData(p_obj->i2c, (uint32_t)data);
|
||||
I2C_GenerateStart(p_obj->i2c);
|
||||
}
|
||||
}
|
||||
|
||||
const PinMap *i2c_master_sda_pinmap()
|
||||
|
|
|
@ -75,12 +75,23 @@ struct i2c_s {
|
|||
IRQn_Type IRQn;
|
||||
TSB_I2C_TypeDef *i2c;
|
||||
I2C_InitTypeDef myi2c;
|
||||
#ifdef DEVICE_I2C_ASYNCH
|
||||
uint32_t event_mask;
|
||||
uint8_t stop;
|
||||
uint8_t state;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct spi_s {
|
||||
TSB_SSP_TypeDef *spi;
|
||||
SPIName module;
|
||||
uint8_t bits;
|
||||
PinName clk_pin;
|
||||
IRQn_Type irqn;
|
||||
#ifdef DEVICE_SPI_ASYNCH
|
||||
uint32_t event_mask;
|
||||
uint8_t state;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct trng_s {
|
||||
|
|
|
@ -69,7 +69,7 @@ reset_reason_t hal_reset_reason_get(void)
|
|||
static uint8_t set_bit_count(uint32_t reg)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
int8_t index = 0;
|
||||
uint8_t index = 0;
|
||||
|
||||
for (index = 0; index < (sizeof(uint32_t) * 8); index++) {
|
||||
if ((reg & (1 << index)) && index != 1) {
|
||||
|
@ -89,6 +89,8 @@ static uint8_t bit_pos(uint32_t reg)
|
|||
return bit_no;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // DEVICE_RESET_REASON
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
/* mbed Microcontroller Library
|
||||
* (C)Copyright TOSHIBA ELECTRONIC DEVICES & STORAGE CORPORATION 2017 All rights reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "rtc_api.h"
|
||||
#include "mbed_mktime.h"
|
||||
|
||||
#define CG_OSCCR_XTEN_SET ((uint32_t)0x00000008)
|
||||
#define CG_OSCCR_DRVOSCL_SET ((uint32_t)0x00000080)
|
||||
|
||||
#define RTC_24_HOUR_MODE ((uint8_t)0x01)
|
||||
#define PAGER_PAGE_ONE ((uint8_t)0x01)
|
||||
#define PAGER_PAGE_ZERO ((uint8_t)0xEE)
|
||||
#define RTC_CLK_ENABLE ((uint8_t)0x08)
|
||||
#define RTC_CLK_DISABLE ((uint8_t)0xE7)
|
||||
#define RTCRESTR_RSTTMR_MASK ((uint8_t)0x20)
|
||||
#define RTCRESTR_RSTTMR_R_RUN ((uint8_t)0x20)
|
||||
#define CGWUPLCR_WUPTL_HIGH_MASK ((uint32_t)0x07FFF000)
|
||||
#define CGWUPLCR_WULEF_MASK ((uint32_t)0x00000002)
|
||||
#define CGWUPLCR_WULEF_R_DONE ((uint32_t)0x00000000)
|
||||
#define CGWUPLCR_WULON_W_ENABLE ((uint32_t)0x00000001)
|
||||
#define RLMLOSCCR_XTEN_RW_ENABLE ((uint32_t)0x00000003)
|
||||
#define ELOSC_CFG_WARM_UP_TIME ((uint64_t)(5000))
|
||||
#define ELOSC_CFG_CLOCK ((uint64_t)(32768))
|
||||
#define HEX2DEC(val) ((val >> 4U) * 10U + val % 16U) // Hex to Dec conversion macro
|
||||
#define DEC2HEX(val) ((val / 10U) * 16U + val % 10U) // Dec to Hex conversion macro
|
||||
|
||||
static int rtc_inited = 0;
|
||||
static int diff_year = 100; //our RTC register only support 2000~2099
|
||||
|
||||
void rtc_init(void)
|
||||
{
|
||||
if (!rtc_inited) {
|
||||
// Enable low-speed oscillator
|
||||
TSB_CG->OSCCR |= CG_OSCCR_XTEN_SET;
|
||||
TSB_CG->OSCCR |= CG_OSCCR_DRVOSCL_SET;
|
||||
|
||||
TSB_RTC->PAGER = 0x00; // Disable clock and alarm
|
||||
|
||||
while ((TSB_RTC->RESTR & RTCRESTR_RSTTMR_MASK) == RTCRESTR_RSTTMR_R_RUN) {
|
||||
// Reset RTC sec counter
|
||||
}
|
||||
|
||||
TSB_RTC->RESTR = 0xE7;
|
||||
|
||||
while ((TSB_RTC->RESTR & RTCRESTR_RSTTMR_MASK) == RTCRESTR_RSTTMR_R_RUN) {
|
||||
// Reset RTC sec counter
|
||||
}
|
||||
|
||||
TSB_RTC->PAGER |= PAGER_PAGE_ONE;
|
||||
TSB_RTC->YEARR = 0x03; // Set leap year state
|
||||
TSB_RTC->MONTHR = RTC_24_HOUR_MODE; // Set hour mode
|
||||
TSB_RTC->PAGER &= PAGER_PAGE_ZERO; // Set hour mode
|
||||
TSB_RTC->YEARR = 0x01; // Set year value
|
||||
TSB_RTC->MONTHR = (uint8_t)0x01; // Set month value
|
||||
TSB_RTC->DATER = (uint8_t)0x01; // Set date value
|
||||
TSB_RTC->DAYR = (uint8_t)0x0; // Set day value
|
||||
TSB_RTC->HOURR = (uint8_t)0x01; // Set hour value
|
||||
TSB_RTC->MINR = (uint8_t)0x02; // Set minute value
|
||||
TSB_RTC->SECR = (uint8_t)0x22; // Set second value
|
||||
TSB_RTC->PAGER |= RTC_CLK_ENABLE; // Enable Clock
|
||||
rtc_inited = 1; // Enable RTC initialzed status
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_free(void)
|
||||
{
|
||||
rtc_inited = 0; // Set status of RTC peripheral driver as DISABLE
|
||||
}
|
||||
|
||||
int rtc_isenabled(void)
|
||||
{
|
||||
return rtc_inited; // Return status of RTC peripheral driver
|
||||
}
|
||||
|
||||
time_t rtc_read(void)
|
||||
{
|
||||
if (!rtc_inited) {
|
||||
// Return invalid time for now!
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tm timeinfo;
|
||||
uint8_t read_1 = 0U;
|
||||
uint8_t read_2 = 0U;
|
||||
|
||||
timeinfo.tm_isdst = 0;//no summer time
|
||||
|
||||
TSB_RTC->PAGER &= PAGER_PAGE_ZERO;
|
||||
|
||||
read_1 = TSB_RTC->SECR; // Get sec value
|
||||
timeinfo.tm_sec = HEX2DEC(read_1);
|
||||
|
||||
do { // Get minute value
|
||||
read_1 = TSB_RTC->MINR;
|
||||
read_2 = TSB_RTC->MINR;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_min = HEX2DEC(read_1);
|
||||
|
||||
do { // Get hour value
|
||||
read_1 = TSB_RTC->HOURR;
|
||||
read_2 = TSB_RTC->HOURR;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_hour = HEX2DEC(read_1);
|
||||
|
||||
do { // Get Month date value
|
||||
read_1 = TSB_RTC->DATER;
|
||||
read_2 = TSB_RTC->DATER;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_mday = HEX2DEC(read_1);
|
||||
|
||||
do { // Get Month value
|
||||
read_1 = TSB_RTC->MONTHR;
|
||||
read_2 = TSB_RTC->MONTHR;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_mon = HEX2DEC(read_1)-1;
|
||||
|
||||
do { // Get weekday value
|
||||
read_1 = TSB_RTC->DAYR;
|
||||
read_2 = TSB_RTC->DAYR;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_wday = HEX2DEC(read_1);
|
||||
|
||||
do { // Get year value
|
||||
read_1 = TSB_RTC->YEARR;
|
||||
read_2 = TSB_RTC->YEARR;
|
||||
} while (read_1 != read_2);
|
||||
timeinfo.tm_year = (HEX2DEC(read_1)+ diff_year);
|
||||
|
||||
time_t t;
|
||||
|
||||
if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
|
||||
return 0;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void rtc_write(time_t t)
|
||||
{
|
||||
if (!rtc_inited) {
|
||||
// Initialize the RTC as not yet initialized
|
||||
rtc_init();
|
||||
}
|
||||
|
||||
struct tm timeinfo;
|
||||
if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
diff_year = timeinfo.tm_year - (timeinfo.tm_year % 100);
|
||||
|
||||
TSB_RTC->PAGER &= RTC_CLK_DISABLE; // Disable clock
|
||||
|
||||
// Check current year is leap year or not
|
||||
if (((timeinfo.tm_year % 4) == 0 && (timeinfo.tm_year % 100) != 0) ||
|
||||
(timeinfo.tm_year % 400) == 0) {
|
||||
TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is a leap year
|
||||
TSB_RTC->YEARR = 0x00;
|
||||
} else if ((timeinfo.tm_year % 4) == 1) {
|
||||
TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is the year following a leap year
|
||||
TSB_RTC->YEARR = 0x01;
|
||||
} else if ((timeinfo.tm_year % 4) == 2) {
|
||||
TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is two years after a leap year
|
||||
TSB_RTC->YEARR = 0x02;
|
||||
} else {
|
||||
TSB_RTC->PAGER |= PAGER_PAGE_ONE; // Current year is three years after a leap year
|
||||
TSB_RTC->YEARR = 0x03;
|
||||
}
|
||||
|
||||
TSB_RTC->PAGER &= PAGER_PAGE_ZERO; // Select PAGE 0
|
||||
TSB_RTC->YEARR = (uint8_t)DEC2HEX((timeinfo.tm_year - diff_year)); // Set year value
|
||||
// Set month value, tm_mon=0 means Jan while 1 is Jan in M3H
|
||||
TSB_RTC->MONTHR = (uint8_t)DEC2HEX((timeinfo.tm_mon+1));
|
||||
TSB_RTC->DATER = (uint8_t)DEC2HEX(timeinfo.tm_mday); // Set date value
|
||||
TSB_RTC->DAYR = (uint8_t)(timeinfo.tm_wday); // Set week day value
|
||||
TSB_RTC->HOURR = (uint8_t)DEC2HEX(timeinfo.tm_hour); // Set hour value
|
||||
TSB_RTC->MINR = (uint8_t)DEC2HEX(timeinfo.tm_min); // Set minute value
|
||||
TSB_RTC->SECR = (uint8_t)DEC2HEX(timeinfo.tm_sec); // Set second value
|
||||
|
||||
// Setting Wait
|
||||
// When stop mode is selected, CaseA or CaseB is need.
|
||||
// CaseA: Wait for RTC 1Hz interrupt.
|
||||
// CaseB: Check the clock register setting.
|
||||
{
|
||||
uint8_t flag = 1;
|
||||
time_t time_read = {0};
|
||||
while (flag) {
|
||||
time_read = rtc_read();
|
||||
if (time_read == t) { // Wait for setting successfully
|
||||
flag = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
TSB_RTC->PAGER |= RTC_CLK_ENABLE; // Enable Clock
|
||||
}
|
|
@ -193,6 +193,8 @@ void serial_free(serial_t *obj)
|
|||
obj->fuart_config.Mode = 0;
|
||||
obj->fuart_config.FlowCtrl = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,6 +216,8 @@ void serial_baud(serial_t *obj, int baudrate)
|
|||
FUART_Init(obj->FUART,&obj->fuart_config);
|
||||
FUART_Enable(obj->FUART);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,6 +254,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
|||
FUART_Init(obj->FUART,&obj->fuart_config);
|
||||
FUART_Enable(obj->FUART);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -363,6 +369,8 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
|
|||
case SERIAL_5:
|
||||
irq_n = INTUART1_IRQn;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((obj->index == SERIAL_4) || (obj->index == SERIAL_5)) {
|
||||
|
@ -428,6 +436,8 @@ void serial_putc(serial_t *obj, int c)
|
|||
case SERIAL_5:
|
||||
FUART_SetTxData(obj->FUART,(uint32_t)c);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,6 +460,8 @@ int serial_readable(serial_t *obj)
|
|||
ret = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -473,6 +485,8 @@ int serial_writable(serial_t *obj)
|
|||
ret = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -490,6 +504,8 @@ void serial_clear(serial_t *obj)
|
|||
case SERIAL_5:
|
||||
FUART_GetRxData(obj->FUART);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,6 +591,8 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
|
|||
}
|
||||
FUART_Enable(obj->FUART);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,17 @@
|
|||
#include "pinmap.h"
|
||||
#include "tmpm46b_ssp.h"
|
||||
|
||||
#define TMPM46B_SPI_2_FMAX 20000000
|
||||
#define TMPM46B_SPI_FMAX 10000000
|
||||
#define SPI_TRANSFER_STATE_IDLE (0U)
|
||||
#define SPI_TRANSFER_STATE_BUSY (1U)
|
||||
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
#define SPI_S(obj) (( struct spi_s *)(&(obj->spi)))
|
||||
#else
|
||||
#define SPI_S(obj) (( struct spi_s *)(obj))
|
||||
#endif
|
||||
|
||||
static const PinMap PinMap_SPI_SCLK[] = {
|
||||
{PK4, SPI_0, PIN_DATA(2, 1)},
|
||||
{PF3, SPI_1, PIN_DATA(5, 1)},
|
||||
|
@ -39,6 +50,13 @@ static const PinMap PinMap_SPI_SCLK[] = {
|
|||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_SLAVE_SCLK[] = {
|
||||
{PK4, SPI_0, PIN_DATA(2, 0)},
|
||||
{PF3, SPI_1, PIN_DATA(5, 0)},
|
||||
{PD3, SPI_2, PIN_DATA(1, 0)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
static const PinMap PinMap_SPI_MOSI[] = {
|
||||
{PK3, SPI_0, PIN_DATA(2, 1)},
|
||||
{PF4, SPI_1, PIN_DATA(5, 1)},
|
||||
|
@ -54,17 +72,19 @@ static const PinMap PinMap_SPI_MISO[] = {
|
|||
};
|
||||
|
||||
static const PinMap PinMap_SPI_SSEL[] = {
|
||||
{PK1, SPI_0, PIN_DATA(2, 1)},
|
||||
{PF6, SPI_1, PIN_DATA(5, 1)},
|
||||
{PD0, SPI_2, PIN_DATA(1, 1)},
|
||||
{PK1, SPI_0, PIN_DATA(2, 2)},
|
||||
{PF6, SPI_1, PIN_DATA(5, 2)},
|
||||
{PD0, SPI_2, PIN_DATA(1, 2)},
|
||||
{NC, NC, 0}
|
||||
};
|
||||
|
||||
#define TMPM46B_SPI_2_FMAX 20000000
|
||||
#define TMPM46B_SPI_FMAX 10000000
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
static inline void state_idle(struct spi_s *obj_s);
|
||||
#endif
|
||||
|
||||
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
SSP_InitTypeDef config;
|
||||
|
||||
// Check pin parameters
|
||||
|
@ -75,24 +95,32 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
|||
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
|
||||
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
|
||||
|
||||
obj->module = (SPIName)pinmap_merge(spi_data, spi_sclk);
|
||||
obj->module = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
||||
MBED_ASSERT((int)obj->module!= NC);
|
||||
obj_s->module = (SPIName)pinmap_merge(spi_data, spi_sclk);
|
||||
obj_s->module = (SPIName)pinmap_merge(spi_data, spi_cntl);
|
||||
MBED_ASSERT((int)obj_s->module!= NC);
|
||||
|
||||
obj_s->clk_pin = sclk;
|
||||
#if DEVICE_SPI_ASYNCH
|
||||
obj_s->state = SPI_TRANSFER_STATE_IDLE;
|
||||
#endif
|
||||
|
||||
// Identify SPI module to use
|
||||
switch ((int)obj->module) {
|
||||
switch ((int)obj_s->module) {
|
||||
case SPI_0:
|
||||
obj->spi = TSB_SSP0;
|
||||
obj_s->irqn = INTSSP0_IRQn;
|
||||
obj_s->spi = TSB_SSP0;
|
||||
break;
|
||||
case SPI_1:
|
||||
obj->spi = TSB_SSP1;
|
||||
obj_s->irqn = INTSSP1_IRQn;
|
||||
obj_s->spi = TSB_SSP1;
|
||||
break;
|
||||
case SPI_2:
|
||||
obj->spi = TSB_SSP2;
|
||||
obj_s->irqn = INTSSP2_IRQn;
|
||||
obj_s->spi = TSB_SSP2;
|
||||
break;
|
||||
default:
|
||||
obj->spi= NULL;
|
||||
obj->module = (SPIName)NC;
|
||||
obj_s->spi= NULL;
|
||||
obj_s->module = (SPIName)NC;
|
||||
error("Cannot found SPI module corresponding with input pins.");
|
||||
break;
|
||||
}
|
||||
|
@ -117,33 +145,40 @@ void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel
|
|||
config.ClkPhase = SSP_PHASE_FIRST_EDGE;
|
||||
config.DataSize = 0x08;
|
||||
|
||||
obj->bits = config.DataSize;
|
||||
obj_s->bits = config.DataSize;
|
||||
config.Mode = SSP_MASTER;
|
||||
SSP_Init(obj->spi, &config);
|
||||
SSP_Init(obj_s->spi, &config);
|
||||
|
||||
// Disable all interrupt
|
||||
|
||||
SSP_SetINTConfig(obj->spi, SSP_INTCFG_NONE);
|
||||
SSP_Enable(obj->spi);
|
||||
SSP_SetINTConfig(obj_s->spi, SSP_INTCFG_NONE);
|
||||
SSP_Enable(obj_s->spi);
|
||||
}
|
||||
|
||||
void spi_free(spi_t *obj)
|
||||
{
|
||||
SSP_Disable(obj->spi);
|
||||
obj->spi = NULL;
|
||||
obj->module = (SPIName)NC;
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
SSP_Disable(obj_s->spi);
|
||||
obj_s->spi = NULL;
|
||||
obj_s->module = (SPIName)NC;
|
||||
}
|
||||
|
||||
void spi_format(spi_t *obj, int bits, int mode, int slave)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
MBED_ASSERT(slave == SSP_MASTER); // Master mode only
|
||||
MBED_ASSERT((slave == SSP_MASTER) || (slave == SSP_SLAVE));
|
||||
|
||||
spi = obj->spi;
|
||||
spi = obj_s->spi;
|
||||
|
||||
SSP_Disable(spi);
|
||||
|
||||
obj->bits = bits;
|
||||
if (slave) {
|
||||
pinmap_pinout(obj_s->clk_pin, PinMap_SPI_SLAVE_SCLK);
|
||||
SSP_SetMSMode(spi, SSP_SLAVE);
|
||||
}
|
||||
|
||||
obj_s->bits = bits;
|
||||
|
||||
SSP_SetDataSize(spi, bits);
|
||||
SSP_SetClkPolarity(spi, (SSP_ClkPolarity)(mode & 0x1));
|
||||
|
@ -154,6 +189,7 @@ void spi_format(spi_t *obj, int bits, int mode, int slave)
|
|||
|
||||
void spi_frequency(spi_t *obj, int hz)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
// Search Freq data
|
||||
|
@ -174,13 +210,13 @@ void spi_frequency(spi_t *obj, int hz)
|
|||
*/
|
||||
MBED_ASSERT((SystemCoreClock / 65024) <= (uint32_t)hz);
|
||||
|
||||
if (obj->module == SPI_2) {
|
||||
if (obj_s->module == SPI_2) {
|
||||
MBED_ASSERT(hz <= TMPM46B_SPI_2_FMAX);
|
||||
} else {
|
||||
MBED_ASSERT(hz <= TMPM46B_SPI_FMAX); // Default value of SPI_0, SPI_1, SPI_2
|
||||
}
|
||||
|
||||
spi = obj->spi;
|
||||
spi = obj_s->spi;
|
||||
fr_gear = SystemCoreClock / hz;
|
||||
if (fr_gear < 48) {
|
||||
cur_cpsdvsr = fr_gear;
|
||||
|
@ -239,9 +275,10 @@ static void spi_clear_FIFOs(TSB_SSP_TypeDef *spi)
|
|||
|
||||
int spi_master_write(spi_t *obj, int value)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
spi = obj->spi;
|
||||
spi = obj_s->spi;
|
||||
// Clear all data in transmit FIFO and receive FIFO
|
||||
spi_clear_FIFOs(spi);
|
||||
// Transmit data
|
||||
|
@ -270,16 +307,64 @@ int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
|
|||
return total;
|
||||
}
|
||||
|
||||
int spi_slave_receive(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
SSP_FIFOState rx_buf_state;
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
spi = obj_s->spi;
|
||||
|
||||
rx_buf_state = SSP_GetFIFOState(spi, SSP_RX);
|
||||
|
||||
if ((rx_buf_state == SSP_FIFO_NORMAL) || (rx_buf_state == SSP_FIFO_FULL)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_slave_read(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
uint8_t ret_value = 0;
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
spi = obj_s->spi;
|
||||
|
||||
ret_value = SSP_GetRxData(spi);
|
||||
|
||||
SSP_Disable(spi);
|
||||
|
||||
return ret_value;
|
||||
}
|
||||
|
||||
void spi_slave_write(spi_t *obj, int value)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
spi = obj_s->spi;
|
||||
|
||||
SSP_SetTxData(spi, value);
|
||||
|
||||
SSP_Enable(spi);
|
||||
}
|
||||
int spi_busy(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
WorkState state;
|
||||
state = SSP_GetWorkState(obj->spi);
|
||||
|
||||
state = SSP_GetWorkState(obj_s->spi);
|
||||
|
||||
return (state == BUSY);
|
||||
}
|
||||
|
||||
uint8_t spi_get_module(spi_t *obj)
|
||||
{
|
||||
return (uint8_t)(obj->module);
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
|
||||
return (uint8_t)(obj_s->module);
|
||||
}
|
||||
|
||||
const PinMap *spi_master_mosi_pinmap()
|
||||
|
@ -321,3 +406,154 @@ const PinMap *spi_slave_cs_pinmap()
|
|||
{
|
||||
return PinMap_SPI_SSEL;
|
||||
}
|
||||
|
||||
#ifdef DEVICE_SPI_ASYNCH
|
||||
|
||||
void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width,
|
||||
uint32_t handler, uint32_t event, DMAUsage hint)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
|
||||
spi = obj_s->spi;
|
||||
|
||||
obj_s->event_mask = event | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
|
||||
// check which use-case we have
|
||||
bool use_tx = (tx != NULL && tx_length > 0);
|
||||
bool use_rx = (rx != NULL && rx_length > 0);
|
||||
|
||||
// don't do anything, if the buffers aren't valid
|
||||
if (!use_tx && !use_rx) {
|
||||
return;
|
||||
}
|
||||
|
||||
// copy the buffers to the SPI object
|
||||
obj->tx_buff.buffer = (void *) tx;
|
||||
obj->tx_buff.length = tx ? tx_length : 0;
|
||||
obj->tx_buff.pos = 0;
|
||||
|
||||
obj->rx_buff.buffer = rx;
|
||||
obj->rx_buff.length = rx ? rx_length : 0;
|
||||
obj->rx_buff.pos = 0;
|
||||
|
||||
NVIC_SetVector(obj_s->irqn, (uint32_t)handler); //receive interrupt
|
||||
NVIC_ClearPendingIRQ(obj_s->irqn);
|
||||
|
||||
obj_s->state = SPI_TRANSFER_STATE_BUSY;
|
||||
|
||||
SSP_SetINTConfig(spi, SSP_INTCFG_ALL);
|
||||
|
||||
if (use_tx) {
|
||||
// Transmit first byte to enter into handler
|
||||
SSP_SetTxData(spi, *(uint8_t *)(tx));
|
||||
obj->tx_buff.pos++;
|
||||
} else if (use_rx) {
|
||||
//if RX only then transmit one dummy byte to enter into handler
|
||||
SSP_SetTxData(spi, 0xFF);
|
||||
}
|
||||
|
||||
SSP_Enable(spi);
|
||||
NVIC_EnableIRQ(obj_s->irqn);
|
||||
}
|
||||
|
||||
uint32_t spi_irq_handler_asynch(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
TSB_SSP_TypeDef* spi;
|
||||
int event = 0;
|
||||
SSP_INTState state = { 0U };
|
||||
|
||||
spi = obj_s->spi;
|
||||
|
||||
if (obj_s->state != SPI_TRANSFER_STATE_BUSY) {
|
||||
event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
state_idle(obj_s);
|
||||
return (event & obj_s->event_mask);
|
||||
}
|
||||
|
||||
state = SSP_GetPostEnableINTState(spi);
|
||||
|
||||
if (state.Bit.TimeOut || state.Bit.Rx) {
|
||||
|
||||
if (obj->rx_buff.pos < obj->rx_buff.length) {
|
||||
*((uint8_t *)obj->rx_buff.buffer + obj->rx_buff.pos) = (uint8_t)SSP_GetRxData(spi);
|
||||
obj->rx_buff.pos++;
|
||||
|
||||
if ((obj->tx_buff.pos == obj->tx_buff.length) && (obj->rx_buff.pos < obj->rx_buff.length)) {
|
||||
// transmit complete but receive pending - dummy write
|
||||
SSP_SetTxData(spi, 0xFF);
|
||||
}
|
||||
|
||||
} else {
|
||||
//Receive complete - dummy read
|
||||
uint8_t dummy = (uint8_t)SSP_GetRxData(spi);
|
||||
(void)dummy;
|
||||
}
|
||||
}
|
||||
|
||||
if (state.Bit.Tx) {
|
||||
|
||||
if (obj->tx_buff.pos < obj->tx_buff.length) {
|
||||
SSP_SetTxData(spi, (*((uint8_t *)obj->tx_buff.buffer + obj->tx_buff.pos) & 0xFF));
|
||||
obj->tx_buff.pos++;
|
||||
|
||||
} else if (obj->rx_buff.pos == obj->rx_buff.length) {
|
||||
// Tx and Rx complete
|
||||
event = SPI_EVENT_COMPLETE | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
state_idle(obj_s);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.Bit.OverRun) {
|
||||
SSP_ClearINTFlag(spi, SSP_INTCFG_ALL);
|
||||
event = SPI_EVENT_ERROR | SPI_EVENT_INTERNAL_TRANSFER_COMPLETE;
|
||||
state_idle(obj_s);
|
||||
}
|
||||
|
||||
return (event & obj_s->event_mask);
|
||||
}
|
||||
|
||||
uint8_t spi_active(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
|
||||
return (obj_s->state != SPI_TRANSFER_STATE_IDLE);
|
||||
}
|
||||
|
||||
void spi_abort_asynch(spi_t *obj)
|
||||
{
|
||||
struct spi_s *obj_s = SPI_S(obj);
|
||||
SSP_InitTypeDef config;
|
||||
|
||||
state_idle(obj_s);
|
||||
|
||||
config.FrameFormat = SSP_FORMAT_SPI;
|
||||
|
||||
// bit_rate = Fsys / (clk_prescale * (clk_rate + 1))
|
||||
config.PreScale = 48;
|
||||
config.ClkRate = 0;
|
||||
|
||||
config.ClkPolarity = SSP_POLARITY_LOW;
|
||||
config.ClkPhase = SSP_PHASE_FIRST_EDGE;
|
||||
config.DataSize = obj_s->bits;
|
||||
|
||||
config.Mode = SSP_MASTER;
|
||||
|
||||
SSP_Init(obj_s->spi, &config);
|
||||
SSP_Enable(obj_s->spi);
|
||||
}
|
||||
|
||||
static inline void state_idle(struct spi_s *obj_s)
|
||||
{
|
||||
NVIC_DisableIRQ(obj_s->irqn);
|
||||
NVIC_ClearPendingIRQ(obj_s->irqn);
|
||||
obj_s->state = SPI_TRANSFER_STATE_IDLE;
|
||||
|
||||
//clean-up
|
||||
spi_clear_FIFOs(obj_s->spi);
|
||||
SSP_Disable(obj_s->spi);
|
||||
SSP_ClearINTFlag(obj_s->spi, SSP_INTCFG_ALL);
|
||||
}
|
||||
|
||||
#endif //DEVICE_SPI_ASYNCH
|
||||
|
|
|
@ -8232,10 +8232,15 @@
|
|||
"PORTOUT",
|
||||
"PWMOUT",
|
||||
"RESET_REASON",
|
||||
"RTC",
|
||||
"SERIAL",
|
||||
"SERIAL_FC",
|
||||
"SPI",
|
||||
"SPISLAVE",
|
||||
"SPI_ASYNCH",
|
||||
"I2C",
|
||||
"I2CSLAVE",
|
||||
"I2C_ASYNCH",
|
||||
"STDIO_MESSAGES",
|
||||
"TRNG",
|
||||
"FLASH",
|
||||
|
|
Loading…
Reference in New Issue