Skip to content

Commit

Permalink
Got UART logging working. Working on enabling uart console to connect…
Browse files Browse the repository at this point in the history
… to logger
  • Loading branch information
danieldegrasse committed Aug 14, 2020
1 parent 0d6a0ac commit cd20145
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 61 deletions.
3 changes: 2 additions & 1 deletion Board.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ extern "C" {
#define Board_LED2 EK_TM4C123GXL_LED_RED
#define Board_BUTTON0 EK_TM4C123GXL_SW1
#define Board_BUTTON1 EK_TM4C123GXL_SW2
#define Board_SDCARD_VCC EK_TM4C123GXL_SDCARD_VCC
#define Board_SDCARD_VCC EK_TM4C123GXL_SDCARD_VCC
#define Board_WRITE_ACTIVITY_LED EK_TM4C123GXL_WRITE_ACTIVITY_LED

#define Board_I2C0 EK_TM4C123GXL_I2C0
#define Board_I2C1 EK_TM4C123GXL_I2C3
Expand Down
4 changes: 3 additions & 1 deletion EK_TM4C123GXL.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ GPIO_PinConfig gpioPinConfigs[] = {
/* EK_TM4C123GXL_LED_GREEN */
GPIOTiva_PF_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
/* EK_TM4C123GXL_SDCARD_VCC */
GPIOTiva_PE_3 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW
GPIOTiva_PA_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
/* EK_TM4C123GXL_WRITE_ACTIVITY_LED */
GPIOTiva_PF_4 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW
};

/*
Expand Down
1 change: 1 addition & 0 deletions EK_TM4C123GXL.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ typedef enum EK_TM4C123GXL_GPIOName {
EK_TM4C123GXL_LED_BLUE,
EK_TM4C123GXL_LED_GREEN,
EK_TM4C123GXL_SDCARD_VCC,
EK_TM4C123GXL_WRITE_ACTIVITY_LED,
EK_TM4C123GXL_GPIOCOUNT
} EK_TM4C123GXL_GPIOName;

Expand Down
103 changes: 98 additions & 5 deletions commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@

#include <string.h>

#include "cli.h"
#include "sd_card.h"

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>

#include "cli.h"
#include "sd_card.h"
#include "uart_logger_task.h"

/* Board-specific functions */
#include "Board.h"

Expand All @@ -36,6 +37,10 @@ static int help(CLIContext *ctx, char **argv, int argc);
static int mount(CLIContext *ctx, char **argv, int argc);
static int unmount(CLIContext *ctx, char **argv, int argc);
static int sdstatus(CLIContext *ctx, char **argv, int argc);
static int sdpwr(CLIContext *ctx, char **argv, int argc);
static int sdwrite(CLIContext *ctx, char **argv, int argc);
static int logfile_size(CLIContext *ctx, char **argv, int argc);
static int connect_log(CLIContext *ctx, char **argv, int argc);

/**
* Declaration of commands. Syntax is as follows:
Expand All @@ -52,7 +57,12 @@ const CmdEntry COMMANDS[] = {
"supply the name of a command after \"help\" for help with that command"},
{"mount", mount, "Mounts the SD card"},
{"unmount", unmount, "Unmounts the SD card"},
{"sdstatus", sdstatus, "Gets the mount status of the SD card"},
{"sdstatus", sdstatus, "Gets the mount and power status of the SD card"},
{"sdpwr", sdpwr,
"Sets the power status of SD card: \"sdpwr on\" or \"sdpwr off\""},
{"sdwrite", sdwrite, "Writes provided string to the SD card"},
{"filesize", logfile_size, "Gets the size of the log file in bytes"},
{"connect_log", connect_log, "Connects to the UART console being logged"},
// Add more entries here.
{NULL, NULL, NULL}};

Expand Down Expand Up @@ -168,7 +178,7 @@ static int unmount(CLIContext *ctx, char **argv, int argc) {
}

/**
* Reports the mount status of the SD card.
* Reports the mount and power status of the SD card.
* @param ctx: CLI context to print to
* @param argv list of arguments
* @param argc argument count
Expand All @@ -178,5 +188,88 @@ static int unmount(CLIContext *ctx, char **argv, int argc) {
static int sdstatus(CLIContext *ctx, char **argv, int argc) {
cli_printf(ctx, "SD card is %s\r\n",
sd_card_mounted() ? "mounted" : "unmounted");
cli_printf(ctx, "SD card power: %s\r\n",
GPIO_read(Board_SDCARD_VCC) ? "on" : "off");
return 0;
}

/**
* Manually controls power to the SD card. Useful for debugging.
* @param ctx: CLI context to print to
* @param argv list of arguments
* @param argc argument count
* @return 0 on success, or another value on failure
*/
static int sdpwr(CLIContext *ctx, char **argv, int argc) {
if (argc != 2) {
cli_printf(ctx, "Unsupported number of arguments\r\n");
return 255;
}
if (strncmp("on", argv[1], 2) == 0) {
GPIO_write(Board_SDCARD_VCC, Board_LED_ON);
cli_printf(ctx, "SD card power on\r\n");
return 0;
} else if (strncmp("off", argv[1], 3) == 0) {
GPIO_write(Board_SDCARD_VCC, Board_LED_OFF);
cli_printf(ctx, "SD card power off\r\n");
return 0;
} else {
cli_printf(ctx, "Unknown argument %s\r\n", argv[1]);
return 255;
}
}

/**
* Writes provided string to the SD card.
* @param ctx: CLI context to print to
* @param argv list of arguments
* @param argc argument count
* @return 0 on success, or another value on failure
*/
static int sdwrite(CLIContext *ctx, char **argv, int argc) {
if (argc != 2) {
cli_printf(ctx, "Unsupported number of arguments\r\n");
return 255;
}
// Check SD card mount status
if (!sd_card_mounted()) {
cli_printf(ctx, "Cannot write to SD card, not mounted\r\n");
return 255;
}
// Write the string to the SD card.
if (write_sd(argv[1], strlen(argv[1])) != strlen(argv[1])) {
cli_printf(ctx, "Write error!\r\n");
return 255;
}
return 0;
}

/**
* Gets the size of the the logfile in bytes.
* @param ctx: CLI context to print to
* @param argv list of arguments
* @param argc argument count
* @return 0 on success, or another value on failure
*/
static int logfile_size(CLIContext *ctx, char **argv, int argc) {
cli_printf(ctx, "SD card file size is: %d\r\n", filesize());
return 0;
}

/**
* Connects directly to the UART device being logged from. Useful for
* situations where the logged device exposes a terminal, and you'd like to
* access it.
* @param ctx: CLI context to print to
* @param argv list of arguments
* @param argc argument count
* @return 0 on success, or another value on failure
*/
static int connect_log(CLIContext *ctx, char **argv, int argc) {
UART_Queue_Elem *elem;
// For now, just read from queue.
FORWARD_UART_LOGS = true;
elem = Queue_get(uart_log_queue);
cli_printf(ctx, "Latest char was %c\r\n", elem->data);
return 0;
}
110 changes: 93 additions & 17 deletions sd_card.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
*
* ============== Required Pins ==================:
* The SD card is driven via SPI. The following pins are used:
* VCC- PE3 (required for hotplugging SD card)
* CLK- PB4
* MISO- PB6
* MOSI- PB7
* CS- PA5
*
* If hotplugging the SD card is desired, PE3 will be pulled high when the
* PF4- SD write activity LED.
* PA2- See below
* If hotplugging the SD card is desired, PA2 will be pulled high when the
* system wants to power the SD card. a MOSFET or BJT will be required because
* PE3 cannot supply enough current for the SD card.
* PA2 cannot supply enough current for the SD card.
*/

/* XDCtools Header files */
Expand All @@ -40,16 +40,18 @@

// Drive number, as well as macros to convert it to a string
#define DRIVE_NUM 0
#define STR(n) #n
#define STR_(n) #n
#define STR(n) STR_(n)

// Global variables.
pthread_cond_t SD_CARD_READY;
pthread_mutex_t SD_CARD_RW_MUTEX;
bool SD_CARD_MOUNTED = false;
SDSPI_Handle SDSPI_HANDLE;
bool FIRST_INIT = true;
FIL LOGFILE;

static bool sd_online(const char *drive_num, FATFS **fs);
static bool open_file(const char *filename, FIL *outfile);

/**
* Runs required setup for the SD card. Should be called before BIOS starts.
Expand All @@ -72,7 +74,7 @@ void sd_setup(void) {
*/
bool attempt_sd_mount(void) {
SDSPI_Params sdspi_params;
FIL logfile;
const char logfilename[] = STR(DRIVE_NUM) ":uart_log.txt";
bool success;
// First, lock the sd card access mutex.
if (pthread_mutex_lock(&SD_CARD_RW_MUTEX) != 0) {
Expand All @@ -86,13 +88,13 @@ bool attempt_sd_mount(void) {
return SD_CARD_MOUNTED;
}
/**
*
*
* The SD Card needs to be aware of the SPI signal before it is powered.
* If the SPI bus has not been setup, it will not be and the MCU will
* reset.
*
* Delay for 1000ms to let the SD card see the bus.
* Don't shorten this delay, I tried and the card needs time to *think*
*
* For this reason, we wait to power up the sd card until after the early
* init of the bus is done (in main).
*/
// Power up the SD card
GPIO_write(Board_SDCARD_VCC, Board_LED_ON);
Expand All @@ -104,9 +106,13 @@ bool attempt_sd_mount(void) {
} else {
System_printf("SPI Bus for Drive %u started\n", DRIVE_NUM);
}
success = SD_CARD_MOUNTED = sd_online(STR(DRIVE_NUM), &(logfile.fs));
success = SD_CARD_MOUNTED = sd_online(STR(DRIVE_NUM), &(LOGFILE.fs));
if (success) {
// Sd card did mount. Signal waiting tasks.
// Sd card did mount. Open the log file for writing.
if (!open_file(logfilename, &LOGFILE)) {
System_abort("SD card is mounted, but cannot write file");
}
// Signal waiting tasks that the SD card is ready.
pthread_cond_broadcast(&SD_CARD_READY);
} else {
// Sd card is not mounted. Undo SPI bus initialization.
Expand All @@ -124,20 +130,22 @@ bool attempt_sd_mount(void) {
* Unmounts the SD card.
*/
void unmount_sd_card(void) {
// First, lock the sd card access mutex.
// First, lock the sd card access mutex.
if (pthread_mutex_lock(&SD_CARD_RW_MUTEX) != 0) {
System_abort("could not lock sd card mutex");
}
// Flush all pending writes to the SD card, and close the log file.
f_sync(&LOGFILE);
f_close(&LOGFILE);
// Power the SD card VCC back off.
GPIO_write(Board_SDCARD_VCC, Board_LED_OFF);
// Undo SPI bus initialization.
SDSPI_close(SDSPI_HANDLE);
SD_CARD_MOUNTED = false;
// Power the SD card VCC back off.
GPIO_write(Board_SDCARD_VCC, Board_LED_OFF);
// Unlock the mutex.
pthread_mutex_unlock(&SD_CARD_RW_MUTEX);
}


/**
* Gets the mount status of the SD card.
* @return true if card is mounted, false otherwise.
Expand Down Expand Up @@ -167,6 +175,46 @@ void wait_sd_ready(void) {
pthread_mutex_unlock(&SD_CARD_RW_MUTEX);
}

/**
* Writes data to the SD card.
* @param data data buffer to write to the SD card.
* @param n number of bytes to write.
* @return number of bytes written, or -1 on error.
*/
int write_sd(void *data, int n) {
FRESULT fresult;
unsigned int bytes_written;
// First, lock the sd card access mutex.
if (pthread_mutex_lock(&SD_CARD_RW_MUTEX) != 0) {
System_abort("could not lock sd card mutex");
}
fresult = f_write(&LOGFILE, data, n, &bytes_written);
// Unlock the mutex
pthread_mutex_unlock(&SD_CARD_RW_MUTEX);
if (fresult) {
return -1;
} else {
// Toggle write activity LED.
GPIO_toggle(Board_WRITE_ACTIVITY_LED);
return (int)bytes_written;
}
}

/**
* Gets the size of the log file in bytes.
* @return size of file in bytes.
*/
int filesize(void) {
int filesize;
// First, lock the sd card access mutex.
if (pthread_mutex_lock(&SD_CARD_RW_MUTEX) != 0) {
System_abort("could not lock sd card mutex");
}
filesize = f_size(&LOGFILE);
pthread_mutex_unlock(&SD_CARD_RW_MUTEX);
return filesize;
}

/**
* Checks if the SD card is online by attempting to check the free cluster
* count.
Expand All @@ -193,4 +241,32 @@ static bool sd_online(const char *drive_num, FATFS **fs) {
System_flush();
return true;
}
}

/**
* Attempts to open the file given by "filename" using the FIL structure
* "outfile"
* @param filename: filename to open, formatted with the drive number
* @param outfile: output file structure to fill
* @return true if file is opened successfully, or false otherwise.
*/
static bool open_file(const char *filename, FIL *outfile) {
FRESULT fresult;
fresult = f_open(outfile, filename, FA_READ | FA_WRITE);
if (fresult != FR_OK) {
System_printf("Creating new file \"%s\"\n", filename);
fresult = f_open(outfile, filename, FA_CREATE_NEW | FA_READ | FA_WRITE);
if (fresult != FR_OK) {
return false;
}
System_flush();
} else {
// Seek to the end of the file.
fresult = f_lseek(outfile, f_size(outfile));
if (fresult != FR_OK) {
f_close(outfile);
return false;
}
}
return true;
}
Loading

0 comments on commit cd20145

Please sign in to comment.