Update repo

This commit is contained in:
hangpersonal committed 2026-09-05 12:09:21 -07:00
1 parent ef5f9a563e
commit dfe8ec02bd
12 files changed
+723 -341

No files matched your search

+1 -1
View File
@@ -42,7 +42,7 @@
<option IS_BUILTIN_EMPTY="false" IS_VALUE_EMPTY="false" id="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH.77573739" name="Add dir to #include search path (--include_path, -I)" superClass="com.ti.ccstudio.buildDefinitions.C2000_22.6.compilerID.INCLUDE_PATH" valueType="includePath">
<listOptionValue builtIn="false" value="${PROJECT_ROOT}"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/device"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/print_support"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/include"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/../C2000Ware/driverlib/f2837xs/driverlib"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/FreeRTOS/Source/portable/CCS/C2000_C28x"/>
<listOptionValue builtIn="false" value="${PROJECT_ROOT}/FreeRTOS/Source/include"/>
@@ -9,8 +9,8 @@ encoding//CPU1_FLASH/device/subdir_rules.mk=UTF-8
encoding//CPU1_FLASH/device/subdir_vars.mk=UTF-8
encoding//CPU1_FLASH/makefile=UTF-8
encoding//CPU1_FLASH/objects.mk=UTF-8
encoding//CPU1_FLASH/print_support/subdir_rules.mk=UTF-8
encoding//CPU1_FLASH/print_support/subdir_vars.mk=UTF-8
encoding//CPU1_FLASH/source/subdir_rules.mk=UTF-8
encoding//CPU1_FLASH/source/subdir_vars.mk=UTF-8
encoding//CPU1_FLASH/sources.mk=UTF-8
encoding//CPU1_FLASH/subdir_rules.mk=UTF-8
encoding//CPU1_FLASH/subdir_vars.mk=UTF-8
@@ -105,56 +105,36 @@ SECTIONS
.bss:cio : > RAMM0
.data : > RAMGSx
.sysmem : > RAMLSxDxGSx
/* Initalized sections go in Flash */
.const : > FLASH5, ALIGN(8)
#else
.pinit : > FLASH1, ALIGN(8)
.ebss : > RAMGSx
.esysmem : > RAMLSxDxGSx
.cio : > RAMM0
/* Initalized sections go in Flash */
.econst : >> FLASH4 | FLASH5, ALIGN(8)
#endif
/*
ramgs0 : > RAMGS0, type=NOINIT
ramgs1 : > RAMGS1, type=NOINIT
*/
ramm0 : > RAMM0, type=NOINIT
ramm1 : > RAMM1, type=NOINIT
/* The following section definitions are for SDFM examples */
/*
Filter_RegsFile : > RAMGS0
Filter1_RegsFile : > RAMGS1, fill=0x1111
Filter2_RegsFile : > RAMGS2, fill=0x2222
Filter3_RegsFile : > RAMGS3, fill=0x3333
Filter4_RegsFile : > RAMGS4, fill=0x4444
Difference_RegsFile : >RAMGS5, fill=0x3333
*/
#if defined(__TI_EABI__)
.TI.ramfunc : {} LOAD = FLASH3,
RUN = RAMGSx,
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
LOAD_END(RamfuncsLoadEnd),
RUN_START(RamfuncsRunStart),
RUN_SIZE(RamfuncsRunSize),
RUN_END(RamfuncsRunEnd),
ALIGN(8)
#else
.TI.ramfunc : {} LOAD = FLASH3,
RUN = RAMGSx,
LOAD_START(_RamfuncsLoadStart),
LOAD_SIZE(_RamfuncsLoadSize),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
RUN_SIZE(_RamfuncsRunSize),
RUN_END(_RamfuncsRunEnd),
ALIGN(8)
#endif
#if defined(__TI_EABI__)
.TI.ramfunc : {} LOAD = FLASH3,
RUN = RAMGSx,
LOAD_START(RamfuncsLoadStart),
LOAD_SIZE(RamfuncsLoadSize),
LOAD_END(RamfuncsLoadEnd),
RUN_START(RamfuncsRunStart),
RUN_SIZE(RamfuncsRunSize),
RUN_END(RamfuncsRunEnd),
ALIGN(8)
#else
.TI.ramfunc : {} LOAD = FLASH3,
RUN = RAMGSx,
LOAD_START(_RamfuncsLoadStart),
LOAD_SIZE(_RamfuncsLoadSize),
LOAD_END(_RamfuncsLoadEnd),
RUN_START(_RamfuncsRunStart),
RUN_SIZE(_RamfuncsRunSize),
RUN_END(_RamfuncsRunEnd),
ALIGN(8)
#endif
}
+1 -16
View File
@@ -1,21 +1,6 @@
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
//--------------------------------------------------------------------------------------------------
// Application specific definitions.
//
// These definitions should be adjusted for your particular hardware and
// application requirements.
//
// THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
// FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
//
// See http://www.freertos.org/a00110.html.
//--------------------------------------------------------------------------------------------------
// Constants provided for debugging and optimization assistance
//void vMainAssertCalled( const char *pcFileName, uint32_t ulLineNumber );
//#define configASSERT( x ) if ((x) == 0) { vMainAssertCalled( __FILE__, __LINE__ ); }
#define configASSERT( x ) if ((x) == 0) { taskDISABLE_INTERRUPTS(); for( ;; ); }
// Constants related to the behavior or the scheduler
@@ -50,7 +35,7 @@ supported, or if both static and dynamic allocation are supported.
the first block of RAM on the LPC device. See the initialization of the heap
in main.c.
*/
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16 * 1024 ) )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24 * 1024 ) )
// Constants that build features in or out
@@ -0,0 +1,60 @@
#ifndef AT24CM02_H_
#define AT24CM02_H_
#include <stdint.h>
#include "FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AT24CM02_CAPACITY_BYTES 262144UL
#define AT24CM02_PAGE_SIZE_BYTES 256U
#define AT24CM02_PAGE_COUNT 1024U
#define AT24CM02_DEFAULT_ADDRESS 0x50U
typedef enum
{
EEPROM_STATUS_SUCCESS = 0,
EEPROM_STATUS_NOT_INITIALIZED,
EEPROM_STATUS_INVALID_ARGUMENT,
EEPROM_STATUS_OUT_OF_RANGE,
EEPROM_STATUS_NO_MEMORY,
EEPROM_STATUS_MUTEX_TIMEOUT,
EEPROM_STATUS_BUS_BUSY,
EEPROM_STATUS_TIMEOUT,
EEPROM_STATUS_NO_ACK,
EEPROM_STATUS_ARBITRATION_LOST
} EEPROM_Status;
// Configure GPIO91/GPIO92 and I2CA for 400-kHz operation. Call this once
// after Device_init() and Device_initGPIO(), before starting the scheduler.
EEPROM_Status EEPROM_init(void);
// Read or write an arbitrary byte range. A write that crosses a 256-byte page
// boundary is automatically split into multiple page-write transactions.
EEPROM_Status EEPROM_read(uint16_t *data, uint32_t address,
uint16_t deviceAddress, uint32_t byteCount,
TickType_t timeoutTicks);
EEPROM_Status EEPROM_write(const uint16_t *data, uint32_t address,
uint16_t deviceAddress, uint32_t byteCount,
TickType_t timeoutTicks);
// Page numbers are one-based (1 through 1024), matching the original driver.
EEPROM_Status EEPROM_pageNumberToAddress(uint16_t pageNumber,
uint32_t *pageAddress);
EEPROM_Status EEPROM_readPage(uint16_t *data, uint16_t deviceAddress,
uint16_t pageNumber, uint16_t byteCount,
TickType_t timeoutTicks);
EEPROM_Status EEPROM_writePage(const uint16_t *data, uint16_t deviceAddress,
uint16_t pageNumber, uint16_t byteCount,
TickType_t timeoutTicks);
const char *EEPROM_statusString(EEPROM_Status status);
#ifdef __cplusplus
}
#endif
#endif // AT24CM02_H_
+134 -117
View File
@@ -8,6 +8,11 @@
// Driverlib headers
#include "driverlib.h"
#include "device.h"
#include "sci.h"
// Customized headers
#include "uart_drv.h"
#include "at24cm02.h"
// FreeRTOS headers
#include "FreeRTOS.h"
@@ -16,33 +21,15 @@
#include "queue.h"
#include "timers.h"
// STDOUT redirection specific
#include "uart_drv.h"
#include "sci.h"
#define LED_R 41U // Red LED
#define LED_B 58U // Blue LED
#define SCI_RXDA_PIN 85U
#define SCI_TXDA_PIN 84U
// --------------------------------------------------------------------
#if defined (__TI_EABI__)
void *malloc(size_t xSize);
#pragma WEAK (malloc)
#endif
#if defined (__TI_EABI__)
// malloc - Traps malloc calls
void *malloc(size_t xSize) {
(void)xSize;
// There should not be a heap defined, trap any attempts to call malloc()
void* malloc(size_t xSize) {
(void) xSize;
taskDISABLE_INTERRUPTS();
for(;;) {
ESTOP0; // Optional: useful during CCS debug
for (;;) {
ESTOP0;
}
}
#pragma WEAK (malloc)
#endif
#if(configAPPLICATION_ALLOCATED_HEAP == 1)
@@ -51,26 +38,36 @@ uint8_t ucHeap[configTOTAL_HEAP_SIZE];
#pragma DATA_ALIGN(ucHeap, portBYTE_ALIGNMENT)
#endif
// UART stdout redirection configuration related functions
// --------------------------------------------------------------------
#define LED_R 41U // Red LED
#define LED_B 58U // Blue LED
#define SCI_RXDA_PIN 85U
#define SCI_TXDA_PIN 84U
// UART: SCIA
void UartSetup(void);
void UartPutChar(uint16_t charToWrite);
// --------------------------------------------------------------------
// Configuration of CPU timer 1
// CPU Timer 1
void configCPUTimer(uint32_t cpuTimer, uint32_t period_us);
__interrupt void timer1_ISR(void);
// --------------------------------------------------------------------
// EEPROM: AT24CM02 (2Mbit)
static EEPROM_Status eepromInitStatus = EEPROM_STATUS_NOT_INITIALIZED;
static uint16_t eepromReadData[AT24CM02_PAGE_SIZE_BYTES];
static uint16_t eepromWriteData[AT24CM02_PAGE_SIZE_BYTES];
void LED_TaskRed(void * pvParameters);
void LED_TaskBlue(void * pvParameters);
// FreeRTOS tasks
void RedLED_Task(void *pvParameters);
void BlueLED_Task(void *pvParameters);
void EEPROM_Task(void *pvParameters);
static SemaphoreHandle_t xSemaphore = NULL;
// --------------------------------------------------------------------
void main(void)
{
void main(void) {
// Initializes device clock and peripherals
Device_init();
@@ -89,6 +86,9 @@ void main(void)
GPIO_setDirectionMode(LED_B, GPIO_DIR_MODE_OUT);
GPIO_writePin(LED_B, 0);
// GPIO91/GPIO92 and I2CA are configured by the EEPROM driver.
eepromInitStatus = EEPROM_init();
// ------------------------------------------------------------------------
// Clear all interrupts and initialize PIE vector table
@@ -119,29 +119,17 @@ void main(void)
// ------------------------------------------------------------------------
// Enable global Interrupts and higher priority real-time debug events
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global real-time interrupt DBGM
EINT;
// Enable Global interrupt INTM
ERTM;
// Enable Global real-time interrupt DBGM
// ------------------------ Redirect STDOUT to SCI ------------------------
//**************************************************************************
// NOTE: SCI Configuration for this example is done in UartSetup()
// As an alternative, the user can configure SCI here in the main, and then
// provide an empty UartSetup() function. UartSetup() must be defined, even
// if it is empty.
//**************************************************************************
// Add the UART device. When fopen is called with a filename that
// begins "uart:", the UART device will be used to handle the file
add_device("uart",
_SSA,
UART_open,
UART_close,
UART_read,
UART_write,
UART_lseek,
UART_unlink,
UART_rename);
add_device("uart", _SSA, UART_open, UART_close, UART_read, UART_write,
UART_lseek, UART_unlink, UART_rename);
// Assign stdout to be a UART device
assert(freopen("uart:", "w", stdout) != NULL);
@@ -149,72 +137,114 @@ void main(void)
// ------------------------------- FreeRTOS -------------------------------
xSemaphore = xSemaphoreCreateBinary();
if(xSemaphore == NULL) {
while(1);
}
// Create tasks dynamically
if(xTaskCreate(LED_TaskRed,
(const char *) "Red LED Task",
256,
NULL,
tskIDLE_PRIORITY + 2,
NULL) != pdPASS) {
ESTOP0;
}
xTaskCreate(RedLED_Task,
(const char*) "RedLED_Task",
256,
NULL,
1,
NULL);
if(xTaskCreate(LED_TaskBlue,
(const char *) "Blue LED Task",
256,
NULL,
tskIDLE_PRIORITY + 1,
NULL) != pdPASS) {
ESTOP0;
}
xTaskCreate(BlueLED_Task,
(const char*) "BlueLED_Task",
256,
NULL,
1,
NULL);
xTaskCreate(EEPROM_Task,
(const char*) "EEPROM_Task",
384,
NULL,
2,
NULL);
// Start the scheduler. This should not return
vTaskStartScheduler();
}
// -----------------------------------------------------------------------------------------
// This is an event-driven task. It sits in a blocked state waiting for
// xSemaphore to be available by calling xSemaphoreTake() with a timeout
// of portMAX_DELAY. Because Timer 1 releases this semaphore every 100 ms,
// the Red LED task will unblock and toggle the LED exactly every 100 ms.
// It is created with a higher priority of tskIDLE_PRIORITY + 2.
void LED_TaskRed(void * pvParameters) {
void RedLED_Task(void *pvParameters) {
(void)pvParameters;
int uart_count = 0;
while(1) {
if(xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
// Toggle red LED
while (1) {
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
GPIO_togglePin(LED_R);
uart_count++;
printf("Hello from FreeRTOS running on the F28377S Coreboard, %d!\r\n", uart_count);
printf("Hello from FreeRTOS running on the F28377S Coreboard, %d!\r\n",
uart_count);
}
}
}
// This is a time-driven task. It simply toggles the blue LED and then puts
// itself to sleep using vTaskDelay(500 / portTICK_PERIOD_MS).
// Based on the RTOS configuration, this creates a 500 ms delay cycle.
// It runs at a lower priority of tskIDLE_PRIORITY + 1.
void LED_TaskBlue(void * pvParameters) {
while(1) {
// Toggle blue LED
void BlueLED_Task(void *pvParameters) {
(void)pvParameters;
while (1) {
GPIO_togglePin(LED_B);
vTaskDelay(500);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
void EEPROM_Task(void *pvParameters) {
uint16_t i;
uint16_t mismatchCount = 0U;
EEPROM_Status status = eepromInitStatus;
const char *operation = "initialization";
(void)pvParameters;
// Allow the EEPROM supply and power-on reset to settle before the first
// command. The datasheet requires at least 100 us after VCC is stable.
vTaskDelay(pdMS_TO_TICKS(2U));
for (i = 0U; i < AT24CM02_PAGE_SIZE_BYTES; i++) {
eepromWriteData[i] = i;
eepromReadData[i] = 0U;
}
if (status == EEPROM_STATUS_SUCCESS) {
operation = "page write";
status = EEPROM_writePage(eepromWriteData,
AT24CM02_DEFAULT_ADDRESS,
AT24CM02_PAGE_COUNT,
AT24CM02_PAGE_SIZE_BYTES,
pdMS_TO_TICKS(50U));
}
if (status == EEPROM_STATUS_SUCCESS) {
operation = "page read";
status = EEPROM_readPage(eepromReadData,
AT24CM02_DEFAULT_ADDRESS,
AT24CM02_PAGE_COUNT,
AT24CM02_PAGE_SIZE_BYTES,
pdMS_TO_TICKS(50U));
}
if (status == EEPROM_STATUS_SUCCESS) {
for (i = 0U; i < AT24CM02_PAGE_SIZE_BYTES; i++) {
if (eepromReadData[i] != eepromWriteData[i]) {
mismatchCount++;
}
}
printf("AT24CM02 page %u test: %s (%u mismatches)\r\n",
AT24CM02_PAGE_COUNT,
(mismatchCount == 0U) ? "PASS" : "FAIL",
mismatchCount);
} else {
printf("AT24CM02 %s failed: %s\r\n",
operation,
EEPROM_statusString(status));
}
vTaskDelete(NULL);
}
// -----------------------------------------------------------------------------------------
// configCPUTimer - This function initializes the selected timer to the
// period specified by the "freq" and "period" variables. The "freq" is
// CPU frequency in Hz and the period in uSeconds. The timer is held in
// the stopped state after configuration.
// This function initializes the selected timer to the period specified
// by the "freq" and "period" variables. The "freq" is CPU frequency
// in Hz and the period in us.
void configCPUTimer(uint32_t cpuTimer, uint32_t period_us) {
uint32_t periodCount, freq = DEVICE_SYSCLK_FREQ;
@@ -226,29 +256,20 @@ void configCPUTimer(uint32_t cpuTimer, uint32_t period_us) {
// Set pre-scale counter to divide by 1 (SYSCLKOUT)
CPUTimer_setPreScaler(cpuTimer, 0);
// Initializes timer control register. The timer is stopped,
// reloaded, free run disabled, and interrupt enabled.
// Additionally, the free and soft bits are set
// Initializes timer control register
CPUTimer_stopTimer(cpuTimer);
CPUTimer_reloadTimerCounter(cpuTimer);
CPUTimer_setEmulationMode(
cpuTimer,
CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT
);
CPUTimer_setEmulationMode(cpuTimer,
CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
CPUTimer_enableInterrupt(cpuTimer);
}
// When Timer 1 fires, the Interrupt Service Routine executes
// xSemaphoreGiveFromISR(). This unlocks the semaphore so a waiting task
// can proceed. portYIELD_FROM_ISR() is then called to force an immediate
// FreeRTOS context switch if the newly unblocked task has a higher priority
// than the interrupted task.
// Timer 1 ISR function
__interrupt void timer1_ISR(void) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(xSemaphore != NULL) {
if (xSemaphore != NULL) {
xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
@@ -257,7 +278,7 @@ __interrupt void timer1_ISR(void) {
// -----------------------------------------------------------------------------------------
// UartSetup - Configures SCIA
// Configures SCIA, baud rate is 115200
void UartSetup(void) {
// SCIA RX: GPIO85
@@ -278,11 +299,10 @@ void UartSetup(void) {
SCI_performSoftwareReset(SCIA_BASE);
SCI_setConfig(SCIA_BASE,
DEVICE_LSPCLK_FREQ,
DEVICE_LSPCLK_FREQ,
115200U,
SCI_CONFIG_WLEN_8 |
SCI_CONFIG_STOP_ONE |
SCI_CONFIG_PAR_NONE);
SCI_CONFIG_STOP_ONE | SCI_CONFIG_PAR_NONE);
SCI_resetChannels(SCIA_BASE);
SCI_resetRxFIFO(SCIA_BASE);
@@ -296,10 +316,7 @@ void UartSetup(void) {
SCI_performSoftwareReset(SCIA_BASE);
}
// UartPutChar - Implements SCI based putchar()
// Implements SCI based putchar()
void UartPutChar(uint16_t charToWrite) {
SCI_writeCharBlockingFIFO(SCIA_BASE, charToWrite);
}
// -----------------------------------------------------------------------------------------
@@ -0,0 +1,504 @@
#include "at24cm02.h"
#include <stdbool.h>
#include <stddef.h>
#include "driverlib.h"
#include "device.h"
#include "semphr.h"
#include "task.h"
#define EEPROM_I2C_BASE I2CA_BASE
#define EEPROM_I2C_BIT_RATE 400000UL
#define EEPROM_SDA_PIN 91U
#define EEPROM_SCL_PIN 92U
#define EEPROM_STATUS_ERROR_MASK (I2C_STS_NO_ACK | I2C_STS_ARB_LOST)
#define EEPROM_CLEARABLE_STATUS_MASK (I2C_STS_NO_ACK | I2C_STS_ARB_LOST | \
I2C_STS_REG_ACCESS_RDY | \
I2C_STS_STOP_CONDITION)
// The AT24CM02 tWR maximum is 10 ms. Use 11 RTOS ticks at a 1-kHz tick rate
// so the actual delay cannot be shortened below 10 ms by tick quantization.
#define EEPROM_WRITE_CYCLE_MS 11U
static SemaphoreHandle_t eepromMutex = NULL;
static bool eepromInitialized = false;
static bool EEPROM_hasTimedOut(TickType_t start, TickType_t timeoutTicks)
{
if(timeoutTicks == portMAX_DELAY)
{
return false;
}
return ((TickType_t)(xTaskGetTickCount() - start) >= timeoutTicks);
}
static void EEPROM_yield(void)
{
if(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
{
taskYIELD();
}
}
static EEPROM_Status EEPROM_statusToError(uint16_t i2cStatus)
{
if((i2cStatus & I2C_STS_ARB_LOST) != 0U)
{
return EEPROM_STATUS_ARBITRATION_LOST;
}
if((i2cStatus & I2C_STS_NO_ACK) != 0U)
{
return EEPROM_STATUS_NO_ACK;
}
return EEPROM_STATUS_SUCCESS;
}
static void EEPROM_abortTransaction(void)
{
I2C_sendStopCondition(EEPROM_I2C_BASE);
I2C_clearStatus(EEPROM_I2C_BASE, EEPROM_CLEARABLE_STATUS_MASK);
}
static EEPROM_Status EEPROM_waitForStatus(uint16_t requestedStatus,
TickType_t start,
TickType_t timeoutTicks)
{
uint16_t status;
EEPROM_Status error;
for(;;)
{
status = I2C_getStatus(EEPROM_I2C_BASE);
error = EEPROM_statusToError(status);
if(error != EEPROM_STATUS_SUCCESS)
{
return error;
}
if((status & requestedStatus) != 0U)
{
return EEPROM_STATUS_SUCCESS;
}
if(EEPROM_hasTimedOut(start, timeoutTicks))
{
return EEPROM_STATUS_TIMEOUT;
}
EEPROM_yield();
}
}
static EEPROM_Status EEPROM_waitForBusIdle(TickType_t start,
TickType_t timeoutTicks)
{
while(I2C_getStopConditionStatus(EEPROM_I2C_BASE) ||
I2C_isBusBusy(EEPROM_I2C_BASE))
{
if(EEPROM_hasTimedOut(start, timeoutTicks))
{
return EEPROM_STATUS_BUS_BUSY;
}
EEPROM_yield();
}
return EEPROM_STATUS_SUCCESS;
}
static uint16_t EEPROM_targetAddress(uint16_t deviceAddress,
uint32_t memoryAddress)
{
return (uint16_t)(deviceAddress | ((memoryAddress >> 16U) & 0x3U));
}
static bool EEPROM_deviceAddressIsValid(uint16_t deviceAddress)
{
// Bits A17:A16 are supplied by the memory address for this device.
return ((deviceAddress <= 0x7CU) && ((deviceAddress & 0x3U) == 0U));
}
static EEPROM_Status EEPROM_writeChunk(const uint16_t *data,
uint32_t address,
uint16_t deviceAddress,
uint16_t byteCount,
TickType_t timeoutTicks)
{
uint16_t i;
TickType_t start = xTaskGetTickCount();
EEPROM_Status status;
status = EEPROM_waitForBusIdle(start, timeoutTicks);
if(status != EEPROM_STATUS_SUCCESS)
{
return status;
}
I2C_clearStatus(EEPROM_I2C_BASE, EEPROM_CLEARABLE_STATUS_MASK);
I2C_setTargetAddress(EEPROM_I2C_BASE,
EEPROM_targetAddress(deviceAddress, address));
I2C_setDataCount(EEPROM_I2C_BASE, (uint16_t)(byteCount + 2U));
I2C_setConfig(EEPROM_I2C_BASE, I2C_CONTROLLER_SEND_MODE);
I2C_sendStartCondition(EEPROM_I2C_BASE);
I2C_sendStopCondition(EEPROM_I2C_BASE);
status = EEPROM_waitForStatus(I2C_STS_TX_DATA_RDY, start, timeoutTicks);
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_putData(EEPROM_I2C_BASE, (uint16_t)((address >> 8U) & 0xFFU));
}
if(status == EEPROM_STATUS_SUCCESS)
{
status = EEPROM_waitForStatus(I2C_STS_TX_DATA_RDY, start,
timeoutTicks);
}
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_putData(EEPROM_I2C_BASE, (uint16_t)(address & 0xFFU));
}
for(i = 0U; (i < byteCount) && (status == EEPROM_STATUS_SUCCESS); i++)
{
status = EEPROM_waitForStatus(I2C_STS_TX_DATA_RDY, start,
timeoutTicks);
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_putData(EEPROM_I2C_BASE, data[i] & 0xFFU);
}
}
if(status == EEPROM_STATUS_SUCCESS)
{
status = EEPROM_waitForStatus(I2C_STS_STOP_CONDITION, start,
timeoutTicks);
}
if(status != EEPROM_STATUS_SUCCESS)
{
EEPROM_abortTransaction();
return status;
}
I2C_clearStatus(EEPROM_I2C_BASE, I2C_STS_STOP_CONDITION);
return EEPROM_STATUS_SUCCESS;
}
static EEPROM_Status EEPROM_readChunk(uint16_t *data, uint32_t address,
uint16_t deviceAddress,
uint16_t byteCount,
TickType_t timeoutTicks)
{
uint16_t i;
TickType_t start = xTaskGetTickCount();
EEPROM_Status status;
status = EEPROM_waitForBusIdle(start, timeoutTicks);
if(status != EEPROM_STATUS_SUCCESS)
{
return status;
}
I2C_clearStatus(EEPROM_I2C_BASE, EEPROM_CLEARABLE_STATUS_MASK);
I2C_setTargetAddress(EEPROM_I2C_BASE,
EEPROM_targetAddress(deviceAddress, address));
I2C_setDataCount(EEPROM_I2C_BASE, 2U);
I2C_setConfig(EEPROM_I2C_BASE, I2C_CONTROLLER_SEND_MODE);
I2C_sendStartCondition(EEPROM_I2C_BASE);
status = EEPROM_waitForStatus(I2C_STS_TX_DATA_RDY, start, timeoutTicks);
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_putData(EEPROM_I2C_BASE, (uint16_t)((address >> 8U) & 0xFFU));
}
if(status == EEPROM_STATUS_SUCCESS)
{
status = EEPROM_waitForStatus(I2C_STS_TX_DATA_RDY, start,
timeoutTicks);
}
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_putData(EEPROM_I2C_BASE, (uint16_t)(address & 0xFFU));
}
if(status == EEPROM_STATUS_SUCCESS)
{
status = EEPROM_waitForStatus(I2C_STS_REG_ACCESS_RDY, start,
timeoutTicks);
}
if(status == EEPROM_STATUS_SUCCESS)
{
I2C_clearStatus(EEPROM_I2C_BASE, I2C_STS_REG_ACCESS_RDY);
I2C_setDataCount(EEPROM_I2C_BASE, byteCount);
I2C_setConfig(EEPROM_I2C_BASE, I2C_CONTROLLER_RECEIVE_MODE);
I2C_sendStartCondition(EEPROM_I2C_BASE);
I2C_sendStopCondition(EEPROM_I2C_BASE);
}
for(i = 0U; (i < byteCount) && (status == EEPROM_STATUS_SUCCESS); i++)
{
status = EEPROM_waitForStatus(I2C_STS_RX_DATA_RDY, start,
timeoutTicks);
if(status == EEPROM_STATUS_SUCCESS)
{
data[i] = I2C_getData(EEPROM_I2C_BASE) & 0xFFU;
}
}
if(status == EEPROM_STATUS_SUCCESS)
{
status = EEPROM_waitForStatus(I2C_STS_STOP_CONDITION, start,
timeoutTicks);
}
if(status != EEPROM_STATUS_SUCCESS)
{
EEPROM_abortTransaction();
return status;
}
I2C_clearStatus(EEPROM_I2C_BASE, I2C_STS_STOP_CONDITION);
return EEPROM_STATUS_SUCCESS;
}
EEPROM_Status EEPROM_init(void)
{
if(eepromMutex == NULL)
{
eepromMutex = xSemaphoreCreateMutex();
if(eepromMutex == NULL)
{
return EEPROM_STATUS_NO_MEMORY;
}
}
GPIO_setMasterCore(EEPROM_SDA_PIN, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_91_SDAA);
GPIO_setDirectionMode(EEPROM_SDA_PIN, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(EEPROM_SDA_PIN, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(EEPROM_SDA_PIN, GPIO_QUAL_ASYNC);
GPIO_setMasterCore(EEPROM_SCL_PIN, GPIO_CORE_CPU1);
GPIO_setPinConfig(GPIO_92_SCLA);
GPIO_setDirectionMode(EEPROM_SCL_PIN, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(EEPROM_SCL_PIN, GPIO_PIN_TYPE_PULLUP);
GPIO_setQualificationMode(EEPROM_SCL_PIN, GPIO_QUAL_ASYNC);
I2C_disableModule(EEPROM_I2C_BASE);
I2C_initController(EEPROM_I2C_BASE, DEVICE_SYSCLK_FREQ,
EEPROM_I2C_BIT_RATE, I2C_DUTYCYCLE_33);
I2C_setBitCount(EEPROM_I2C_BASE, I2C_BITCOUNT_8);
I2C_setAddressMode(EEPROM_I2C_BASE, I2C_ADDR_MODE_7BITS);
I2C_setEmulationMode(EEPROM_I2C_BASE, I2C_EMULATION_FREE_RUN);
I2C_disableFIFO(EEPROM_I2C_BASE);
I2C_disableInterrupt(EEPROM_I2C_BASE, I2C_INT_ARB_LOST |
I2C_INT_NO_ACK | I2C_INT_REG_ACCESS_RDY |
I2C_INT_RX_DATA_RDY | I2C_INT_TX_DATA_RDY |
I2C_INT_STOP_CONDITION | I2C_INT_ADDR_TARGET |
I2C_INT_RXFF | I2C_INT_TXFF);
I2C_clearStatus(EEPROM_I2C_BASE, EEPROM_CLEARABLE_STATUS_MASK);
I2C_enableModule(EEPROM_I2C_BASE);
eepromInitialized = true;
return EEPROM_STATUS_SUCCESS;
}
EEPROM_Status EEPROM_read(uint16_t *data, uint32_t address,
uint16_t deviceAddress, uint32_t byteCount,
TickType_t timeoutTicks)
{
EEPROM_Status status;
uint32_t chunkSize;
if(!eepromInitialized)
{
return EEPROM_STATUS_NOT_INITIALIZED;
}
if((data == NULL) || (byteCount == 0UL) ||
!EEPROM_deviceAddressIsValid(deviceAddress))
{
return EEPROM_STATUS_INVALID_ARGUMENT;
}
if((address >= AT24CM02_CAPACITY_BYTES) ||
(byteCount > (AT24CM02_CAPACITY_BYTES - address)))
{
return EEPROM_STATUS_OUT_OF_RANGE;
}
if(xSemaphoreTake(eepromMutex, timeoutTicks) != pdTRUE)
{
return EEPROM_STATUS_MUTEX_TIMEOUT;
}
status = EEPROM_STATUS_SUCCESS;
while((byteCount != 0UL) && (status == EEPROM_STATUS_SUCCESS))
{
// I2CCNT is 16-bit; keep chunks moderate and avoid a block-address
// change in the middle of an I2C transaction.
chunkSize = 0x10000UL - (address & 0xFFFFUL);
if(chunkSize > byteCount)
{
chunkSize = byteCount;
}
if(chunkSize > 0xFFFFUL)
{
chunkSize = 0xFFFFUL;
}
status = EEPROM_readChunk(data, address, deviceAddress,
(uint16_t)chunkSize, timeoutTicks);
address += chunkSize;
data += chunkSize;
byteCount -= chunkSize;
}
xSemaphoreGive(eepromMutex);
return status;
}
EEPROM_Status EEPROM_write(const uint16_t *data, uint32_t address,
uint16_t deviceAddress, uint32_t byteCount,
TickType_t timeoutTicks)
{
EEPROM_Status status;
uint32_t chunkSize;
if(!eepromInitialized)
{
return EEPROM_STATUS_NOT_INITIALIZED;
}
if((data == NULL) || (byteCount == 0UL) ||
!EEPROM_deviceAddressIsValid(deviceAddress))
{
return EEPROM_STATUS_INVALID_ARGUMENT;
}
if((address >= AT24CM02_CAPACITY_BYTES) ||
(byteCount > (AT24CM02_CAPACITY_BYTES - address)))
{
return EEPROM_STATUS_OUT_OF_RANGE;
}
if(xSemaphoreTake(eepromMutex, timeoutTicks) != pdTRUE)
{
return EEPROM_STATUS_MUTEX_TIMEOUT;
}
status = EEPROM_STATUS_SUCCESS;
while((byteCount != 0UL) && (status == EEPROM_STATUS_SUCCESS))
{
chunkSize = AT24CM02_PAGE_SIZE_BYTES -
(address & (AT24CM02_PAGE_SIZE_BYTES - 1U));
if(chunkSize > byteCount)
{
chunkSize = byteCount;
}
status = EEPROM_writeChunk(data, address, deviceAddress,
(uint16_t)chunkSize, timeoutTicks);
if(status == EEPROM_STATUS_SUCCESS)
{
if(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING)
{
vTaskDelay(pdMS_TO_TICKS(EEPROM_WRITE_CYCLE_MS));
}
else
{
DEVICE_DELAY_US((uint32_t)EEPROM_WRITE_CYCLE_MS * 1000UL);
}
}
address += chunkSize;
data += chunkSize;
byteCount -= chunkSize;
}
xSemaphoreGive(eepromMutex);
return status;
}
EEPROM_Status EEPROM_pageNumberToAddress(uint16_t pageNumber,
uint32_t *pageAddress)
{
if(pageAddress == NULL)
{
return EEPROM_STATUS_INVALID_ARGUMENT;
}
if((pageNumber == 0U) || (pageNumber > AT24CM02_PAGE_COUNT))
{
return EEPROM_STATUS_OUT_OF_RANGE;
}
*pageAddress = ((uint32_t)pageNumber - 1UL) *
AT24CM02_PAGE_SIZE_BYTES;
return EEPROM_STATUS_SUCCESS;
}
EEPROM_Status EEPROM_readPage(uint16_t *data, uint16_t deviceAddress,
uint16_t pageNumber, uint16_t byteCount,
TickType_t timeoutTicks)
{
uint32_t address;
EEPROM_Status status;
if((byteCount == 0U) || (byteCount > AT24CM02_PAGE_SIZE_BYTES))
{
return EEPROM_STATUS_INVALID_ARGUMENT;
}
status = EEPROM_pageNumberToAddress(pageNumber, &address);
if(status != EEPROM_STATUS_SUCCESS)
{
return status;
}
return EEPROM_read(data, address, deviceAddress, byteCount, timeoutTicks);
}
EEPROM_Status EEPROM_writePage(const uint16_t *data, uint16_t deviceAddress,
uint16_t pageNumber, uint16_t byteCount,
TickType_t timeoutTicks)
{
uint32_t address;
EEPROM_Status status;
if((byteCount == 0U) || (byteCount > AT24CM02_PAGE_SIZE_BYTES))
{
return EEPROM_STATUS_INVALID_ARGUMENT;
}
status = EEPROM_pageNumberToAddress(pageNumber, &address);
if(status != EEPROM_STATUS_SUCCESS)
{
return status;
}
return EEPROM_write(data, address, deviceAddress, byteCount, timeoutTicks);
}
const char *EEPROM_statusString(EEPROM_Status status)
{
static const char *const descriptions[] =
{
"success",
"not initialized",
"invalid argument",
"address out of range",
"FreeRTOS heap exhausted",
"mutex timeout",
"I2C bus busy",
"I2C timeout",
"I2C no acknowledgement",
"I2C arbitration lost"
};
if((uint16_t)status >=
(uint16_t)(sizeof(descriptions) / sizeof(descriptions[0])))
{
return "unknown status";
}
return descriptions[(uint16_t)status];
}