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

@@ -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];
}
@@ -0,0 +1,327 @@
/*****************************************************************************/
//
// Copyright 2001, 2002 Georges Menie (www.menie.org)
// stdarg version contributed by Christian Ettinger
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
/*****************************************************************************/
/*****************************************************************************/
// putchar is the only external dependency for this file,
// if you have a working putchar, leave it commented out.
// If not, uncomment the define below and
// replace outbyte(c) by your own function call.
/*****************************************************************************/
#define TEST_PRINTF
#include "sci.h"
#define putchar(c) UartPutChar(c)
extern void UartPutChar(uint16_t charToWrite);
#include <stdarg.h>
static int tiny_print(char **out, const char *format, va_list args, unsigned int buflen);
static void printchar(char **str, int c, char *buflimit)
{
//extern int putchar(int c);
if (str)
{
if( buflimit == ( char * ) 0 )
{
// Limit of buffer not known, write charater to buffer
**str = (char)c;
++(*str);
}
else if( ( ( unsigned long ) *str ) < ( ( unsigned long ) buflimit ) )
{
// With known limit of buffer, write character
**str = (char)c;
++(*str);
}
}
else
{
(void)putchar(c);
}
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad, char *buflimit)
{
register int pc = 0, padchar = ' ';
if (width > 0)
{
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT))
{
for ( ; width > 0; --width)
{
printchar (out, padchar, buflimit);
++pc;
}
}
for ( ; *string ; ++string)
{
printchar (out, *string, buflimit);
++pc;
}
for ( ; width > 0; --width)
{
printchar (out, padchar, buflimit);
++pc;
}
return pc;
}
// The following should be enough for 32 bit int
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase, char *buflimit)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = (unsigned int)i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad, buflimit);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = (unsigned int)-i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = (unsigned int)u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = (char)(t + '0');
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-', buflimit);
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad, buflimit);
}
static int tiny_print(char **out, const char *format, va_list args, unsigned int buflen)
{
register int width, pad;
register int pc = 0;
char scr[2], *buflimit;
if( buflen == 0 )
{
buflimit = (char *) 0;
}
else
{
/* Calculate the last valid buffer space, leaving space for the NULL
terminator. */
buflimit = (*out) + (buflen - 1);
}
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
width = pad = 0;
if (*format == '\0') break;
if (*format == '%') goto out;
if (*format == '-') {
++format;
pad = PAD_RIGHT;
}
while (*format == '0') {
++format;
pad |= PAD_ZERO;
}
for ( ; *format >= '0' && *format <= '9'; ++format) {
width *= 10;
width += *format - '0';
}
if( *format == 's' ) {
register char *s = (char *)va_arg( args, int32_t );
pc += prints (out, s?s:"(null)", width, pad, buflimit);
continue;
}
if( *format == 'd' ) {
pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a', buflimit);
continue;
}
if( *format == 'x' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a', buflimit);
continue;
}
if( *format == 'X' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A', buflimit);
continue;
}
if( *format == 'u' ) {
pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a', buflimit);
continue;
}
if( *format == 'c' ) {
/* char are converted to int then pushed on the stack */
scr[0] = (char)va_arg( args, int );
scr[1] = '\0';
pc += prints (out, scr, width, pad, buflimit);
continue;
}
}
else {
out:
printchar (out, *format, buflimit);
++pc;
}
}
if (out) **out = '\0';
va_end( args );
return pc;
}
int printf(const char *format, ...)
{
va_list args;
va_start(args, format);
return tiny_print(0, format, args, 0);
}
int sprintf(char *out, const char *format, ...)
{
va_list args;
va_start(args, format);
return tiny_print(&out, format, args, 0);
}
int snprintf( char *buf, unsigned int count, const char *format, ... )
{
va_list args;
(void) count;
va_start(args, format);
return tiny_print(&buf, format, args, count);
}
#ifdef TEST_PRINTF
int checkPrintf(void)
{
char *ptr = "Hello world!";
char *np = 0;
int i = 5;
unsigned int bs = sizeof(int)*8;
int mi;
char buf[80];
mi = (1 << (bs-1)) + 1;
printf("Ptr string = %s \r\n", ptr);
printf("printf test\r\n");
printf("%s is null pointer\r\n", np);
printf("%d = 5\r\n", i);
printf("%d = - max int\r\n", mi);
printf("char %c = 'a'\r\n", 'a');
printf("hex %x = ff\r\n", 0xff);
printf("hex %02x = 00\r\n", 0);
printf("signed %d = unsigned %u = hex %x\r\n", -3, -3, -3);
printf("%d %s(s)%", 0, "message");
printf("\r\n");
printf("%d %s(s) with %%\r\n", 0, "message");
sprintf(buf, "justif: \"%-10s\"\r\n", "left"); printf("%s", buf);
sprintf(buf, "justif: \"%10s\"\r\n", "right"); printf("%s", buf);
sprintf(buf, " 3: %04d zero padded\r\n", 3); printf("%s", buf);
sprintf(buf, " 3: %-4d left justif.\r\n", 3); printf("%s", buf);
sprintf(buf, " 3: %4d right justif.\r\n", 3); printf("%s", buf);
sprintf(buf, "-3: %04d zero padded\r\n", -3); printf("%s", buf);
sprintf(buf, "-3: %-4d left justif.\r\n", -3); printf("%s", buf);
sprintf(buf, "-3: %4d right justif.\r\n", -3); printf("%s", buf);
return 0;
}
/*
* if you compile this file with
* gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
* you will get a normal warning:
* printf.c:214: warning: spurious trailing `%' in format
* this line is testing an invalid % at the end of the format string.
*
* this should display (on 32bit int machine) :
*
* Hello world!
* printf test
* (null) is null pointer
* 5 = 5
* -2147483647 = - max int
* char a = 'a'
* hex ff = ff
* hex 00 = 00
* signed -3 = unsigned 4294967293 = hex fffffffd
* 0 message(s)
* 0 message(s) with %
* justif: "left "
* justif: " right"
* 3: 0003 zero padded
* 3: 3 left justif.
* 3: 3 right justif.
* -3: -003 zero padded
* -3: -3 left justif.
* -3: -3 right justif.
*/
#endif
/* To keep linker happy. */
int write(int i, char* c, int n)
{
(void)i;
(void)n;
(void)c;
return 0;
}
@@ -0,0 +1,144 @@
/*****************************************************************************/
/* UART_LOWLEV.C - Example user-defined device. */
/*****************************************************************************/
#include <file.h>
#include "uart_drv.h"
//#include "uart.h"
extern void UartSetup();
extern void UartPutChar(int charToWrite);
/*****************************************************************************/
/* This is a sample implementation of a user-defined device. The device */
/* must define the seven basic functions (open, close, read, write, lseek, */
/* unlink, rename). These are expected to behave just like the Unix */
/* functions of these names. Some devices might not have a reasonable */
/* action to take for some functions; a UART or TTY device might not be */
/* lseek-able, but can still be opened and written to. A device is added */
/* using the add_device() RTS function call (q.v.). */
/*****************************************************************************/
/* The low-level interface is based on file names and file descriptors. */
/* The file names don't need to be valid Unix file names, but must mean */
/* something to the device. The device must keep track of its own file */
/* descriptors, which will be used by the calling functions to read and */
/* write to the device. If there can only be one instance of a "file" on a */
/* device, the file descriptor doesn't matter much, so just pass a */
/* non-negative integer such as zero. */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* UART_open() */
/* */
/*****************************************************************************/
int UART_open(const char *path, unsigned flags, int llv_fd)
{
/*-----------------------------------------------------------------------*/
/* Only one UART device exists (_SSA). For an _SSA device, file names */
/* are not meaningful, so ignore the file name. */
/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Don't allow attempts to open the UART device that aren't O_WRONLY. */
/*-----------------------------------------------------------------------*/
if (!(flags & O_WRONLY)) return -1;
/*-----------------------------------------------------------------------*/
/* Set up the UART */
/*-----------------------------------------------------------------------*/
UartSetup();
/*-----------------------------------------------------------------------*/
/* Arbitrarily give it file descriptor 1. File descriptors are */
/* device-specific; this file descriptor 1 is not the same as HOST file */
/* descriptor 1 (stdout). */
/*-----------------------------------------------------------------------*/
return 1;
}
/*****************************************************************************/
/* */
/* UART_close() */
/* */
/*****************************************************************************/
int UART_close(int dev_fd)
{
/*-----------------------------------------------------------------------*/
/* Only one UART device exists, so we don't do anything upon close. */
/*-----------------------------------------------------------------------*/
return 0;
}
/*****************************************************************************/
/* */
/* UART_read() reads *at most* count bytes. */
/* */
/*****************************************************************************/
int UART_read(int dev_fd, char *buf, unsigned count)
{
/*-----------------------------------------------------------------------*/
/* Only one UART device exists, and it is write-only, so return error */
/*-----------------------------------------------------------------------*/
return -1;
}
/*****************************************************************************/
/* */
/* UART_write() */
/* */
/*****************************************************************************/
int UART_write(int dev_fd, const char *buf, unsigned count)
{
unsigned i;
/*-----------------------------------------------------------------------*/
/* Output character-by-character */
/*-----------------------------------------------------------------------*/
for (i=0; i < count; i++)
UartPutChar(buf[i]);
return count;
}
/*****************************************************************************/
/* */
/* UART_lseek() */
/* */
/*****************************************************************************/
off_t UART_lseek(int dev_fd, off_t offset, int origin)
{
/*-----------------------------------------------------------------------*/
/* lseek is not possible on UART. */
/*-----------------------------------------------------------------------*/
return -1;
}
/*****************************************************************************/
/* */
/* UART_unlink() */
/* */
/*****************************************************************************/
int UART_unlink(const char *path)
{
/*-----------------------------------------------------------------------*/
/* unlink is not possible on UART */
/*-----------------------------------------------------------------------*/
return -1;
}
/*****************************************************************************/
/* */
/* UART_rename() */
/* */
/*****************************************************************************/
/* rename is unusual among the low-level functions in that it is also */
/* specified in the ISO C standard. It has the same prototype and */
/* semantics, so it's not really an issue. */
/*****************************************************************************/
int UART_rename(const char *old_name, const char *new_name)
{
/*-----------------------------------------------------------------------*/
/* rename is not possible on UART */
/*-----------------------------------------------------------------------*/
return -1;
}