Added new features to TMPM46B

pull/11118/head
Ganesh Ramachandran 2019-07-29 17:41:32 +05:30
parent 033fffea84
commit edf36fb2ae
18 changed files with 984 additions and 299 deletions

View File

@ -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;

View File

@ -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"

View File

@ -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
}
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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()

View File

@ -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 {

View File

@ -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

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -8232,10 +8232,15 @@
"PORTOUT",
"PWMOUT",
"RESET_REASON",
"RTC",
"SERIAL",
"SERIAL_FC",
"SPI",
"SPISLAVE",
"SPI_ASYNCH",
"I2C",
"I2CSLAVE",
"I2C_ASYNCH",
"STDIO_MESSAGES",
"TRNG",
"FLASH",