본문 바로가기
DSP, MCU/TMS320F2838x (C28x)

TMS320F28388D ] 터미널 모니터와 메모리 덤프

by eteo 2023. 1. 10.

 

 

 

터미널 모니터란 시스템의 상황을 모니터하고 터미널에 명령어를 쳐서 여러가지 일을 수행하게끔 하기 위해 윈도우의 명령프롬프트 처럼 MCU에 Command Line Interface를 구현 것을 말한다.

 

 

내가 직접 구현한건 아니고 유튜버 baram 님의 영상을 보고 공부하려고 아래 출처  stm32 코드를 가져와 이식했다.

 

출처 :

https://github.com/chcbaram/stm32f411

 

GitHub - chcbaram/stm32f411

Contribute to chcbaram/stm32f411 development by creating an account on GitHub.

github.com

 

 

 

 

 

 

C28x 코어는 데이터 타입이 STM32와 달라서 주의할 부분이 있다. char 가 2 byte, int가 2 byte 이다.

 

 

 

 

 

 

그외에는 SCI 의 수신, 송신 둘다 링버퍼를 사용하고 main loop 에서 polling 으로 링버퍼를 체크해 송수신하는 것으로 했다. 참고로 이 보드의 SCI 는 DMA 버스에 연결이 안되어있다.

 

그리고 데이터 타입이 다르니 cli의 메모리 덤프 부분도 수정하였다.

 

 

프로젝트 구조

 

 

 

 

 

main.c

#include "main.h"

void main(void)
{

    Device_init();

    Interrupt_initModule();
    Interrupt_initVectorTable();

    cliInit();
    uartInit();

    cliOpen(_DEF_UART1, 115200);

    Interrupt_enableMaster();

    for(;;)
    {
        SCI_readPolling(_DEF_UART1);
        SCI_writePolling(_DEF_UART1);
        cliMain();
    }
}

 

 

 

 

uart.c

/*
 * uart.c
 *
 *  Created on: 2020. 12. 8.
 *      Author: baram
 *      revised by : Jo
 */


#include "uart.h"
#include "qbuffer.h"

static bool is_open[UART_MAX_CH];

static qbuffer_t rx_qbuffer[UART_MAX_CH];
static qbuffer_t tx_qbuffer[UART_MAX_CH];
static uint16_t rx_buf[512];
static uint16_t tx_buf[512];

static uint32_t SCI_getBaud(uint32_t base, uint32_t lspclkHz);
static void SCI_writeChars(uint32_t base, const uint16_t * const array, uint16_t length);

static uint32_t sci_base[UART_MAX_CH] =
{
 SCIA_BASE
};

bool uartInit(void)
{
    int i;
  for (i=0; i<UART_MAX_CH; i++)
  {
      is_open[i] = false;
  }


  return true;
}

bool uartOpen(uint8_t ch, uint32_t baud)
{
  bool ret = false;


  switch(ch)
  {
    case _DEF_UART1:

        GPIO_setMasterCore(DEVICE_GPIO_PIN_SCIRXDA, GPIO_CORE_CPU1);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_SCIRXDA);
        GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_DIR_MODE_IN);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_SCIRXDA, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCIRXDA, GPIO_QUAL_ASYNC);

        GPIO_setMasterCore(DEVICE_GPIO_PIN_SCITXDA, GPIO_CORE_CPU1);
        GPIO_setPinConfig(DEVICE_GPIO_CFG_SCITXDA);
        GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_DIR_MODE_OUT);
        GPIO_setPadConfig(DEVICE_GPIO_PIN_SCITXDA, GPIO_PIN_TYPE_STD);
        GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCITXDA, GPIO_QUAL_ASYNC);

        SCI_performSoftwareReset(SCIA_BASE);

        SCI_setConfig(SCIA_BASE, DEVICE_LSPCLK_FREQ, 115200, (SCI_CONFIG_WLEN_8 |
                                                            SCI_CONFIG_STOP_ONE |
                                                            SCI_CONFIG_PAR_NONE));
        SCI_resetChannels(SCIA_BASE);
        SCI_resetRxFIFO(SCIA_BASE);
        SCI_resetTxFIFO(SCIA_BASE);
        SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_TXFF | SCI_INT_RXFF);

        SCI_enableFIFO(SCIA_BASE);
        SCI_enableModule(SCIA_BASE);
        SCI_performSoftwareReset(SCIA_BASE);
        SCI_resetRxFIFO(SCIA_BASE);


      qbufferCreate(&rx_qbuffer[ch], &rx_buf[0], 512);
      qbufferCreate(&tx_qbuffer[ch], &tx_buf[0], 512);

        ret = true;
        is_open[ch] = true;

        rx_qbuffer[ch].in  = 0;
        rx_qbuffer[ch].out = rx_qbuffer[ch].in;

      break;
    default:
        break;
  }

  return ret;
}

uint32_t uartAvailable(uint8_t ch)
{
  uint32_t ret = 0;

  switch(ch)
  {
    case _DEF_UART1:
      ret = qbufferAvailable(&rx_qbuffer[ch]);
      break;
    default:
        break;
  }

  return ret;
}

uint16_t uartRead(uint8_t ch)
{
  uint16_t ret = 0;

  switch(ch)
  {
    case _DEF_UART1:
      qbufferRead(&rx_qbuffer[ch], &ret, 1);
      break;
    default:
        break;
  }

  return ret;
}

uint32_t uartWrite(uint8_t ch, uint16_t *p_data, uint32_t length)
{
  uint32_t ret = 0;

  switch(ch)
  {
    case _DEF_UART1:
        qbufferWrite(&tx_qbuffer[ch], p_data, length);
//        SCI_writeChars(sci_base[ch], p_data, length);
        ret = length;
      break;
    default:
        break;
  }

  return ret;
}

uint32_t uartPrintf(uint8_t ch, char *fmt, ...)
{
  char buf[256];
  va_list args;
  int len;
  uint32_t ret = 0;

  va_start(args, fmt);
  len = vsnprintf(buf, 256, fmt, args);

  ret = uartWrite(ch, (uint16_t *)buf, len);

  va_end(args);

  return ret;
}

uint32_t uartGetBaud(uint8_t ch)
{
  uint32_t ret = 0;


  switch(ch)
  {
    case _DEF_UART1:
      ret = SCI_getBaud(sci_base[ch], DEVICE_LSPCLK_FREQ);
      break;
    default:
        break;
  }

  return ret;
}

void SCI_readPolling(uint8_t ch)
{
    uint16_t receivedChar;

    if(SCI_getRxFIFOStatus(sci_base[ch]) != SCI_FIFO_RX0)
    {
        receivedChar = ((uint16_t)(HWREGH(SCIA_BASE + SCI_O_RXBUF) & SCI_RXBUF_SAR_M));
        qbufferWrite(&rx_qbuffer[ch], &receivedChar, 1);
    }
}


void SCI_writePolling(uint8_t ch)
{

    ASSERT(SCI_isBaseValid(sci_base[ch]));

    if(SCI_getTxFIFOStatus(sci_base[ch]) != SCI_FIFO_TX16 && qbufferAvailable(&tx_qbuffer[ch]) != 0)
    {

        uint16_t ret = 0;
        qbufferRead(&tx_qbuffer[ch], &ret, 1);

        HWREGH(sci_base[ch] + SCI_O_TXBUF) = ret;
    }
}

static uint32_t SCI_getBaud(uint32_t base, uint32_t lspclkHz)
{
    uint32_t baud;

    baud = lspclkHz /
            ((1U + (uint32_t)((uint32_t)(HWREGH(base + SCI_O_HBAUD) << 8U) |
               HWREGH(base + SCI_O_LBAUD))) * 8U);

    return baud;

}

// Blocking 방식의 송신 함수
static void SCI_writeChars(uint32_t base, const uint16_t * const array, uint16_t length)
{

    ASSERT(SCI_isBaseValid(base));

    uint16_t i;

    for(i = 0U; i < length; i++)
    {
        while(SCI_getTxFIFOStatus(base) == SCI_FIFO_TX16)
        { }
        HWREGH(base + SCI_O_TXBUF) = array[i];
    }
}

// 워닝 제거용
const void *ptr;
void disableWarning()
{
    ptr = &is_open;
    ptr = SCI_writeChars;
}

 

 

 

 

 

 

메모리 덤프

void cliMemoryDump(cli_args_t *args)
{
  int idx, size = 16;
  unsigned long *addr;
  int idx1, i;
  unsigned int *ascptr;
  unsigned int *intptr;
  unsigned int asc_h, asc_l;

  int    argc = args->argc;
  char **argv = args->argv;

  if(args->argc < 1)
  {
    cliPrintf(">> md addr [size] \r\n");
    return;
  }

  if(argc > 1)
  {
    size = (int)strtoul((const char * ) argv[1], (char **)NULL, (int) 0);
  }
  addr   = (unsigned long *)(void *)strtoul((const char * ) argv[0], (char **)NULL, (int) 0);
  ascptr = (unsigned int *)(void *)addr;
  intptr = (unsigned int *)(void *)addr;

  cliPrintf("\r\n      Address    0001 0203 0405 0607 0809 0A0B 0C0D 0E0F");
  cliPrintf("\r\n    ===========  =======================================");

  cliPrintf("\r\n   ");
  for (idx = 0; idx<size; idx++)
  {
    if((idx%4) == 0)
    {
        cliPrintf(" 0x%08lX: ", (unsigned long)(void *)addr);
    }
    cliPrintf(" %04X", *intptr++);
    cliPrintf(" %04X", *intptr);

    if ((idx%4) == 3)
    {
      cliPrintf ("  |");
      for (idx1= 0; idx1< 4; idx1++)
      {
        for (i=0;i<2;i++)
        {
            asc_h = (*ascptr) >> 8U;
            asc_l = (*ascptr) & 0xFFU;

          if (asc_h > 0x1f && asc_h < 0x7f) cliPrintf("%c", asc_h);
          else cliPrintf(".");
          if (asc_l > 0x1f && asc_l < 0x7f) cliPrintf("%c", asc_l);
          else cliPrintf(".");

          ascptr++;
        }
      }
      cliPrintf("|\r\n   ");
    }
    addr++;
    intptr++;
  }
}