leon-myuart.c 5.64 KB
/* -----------------------------------------------------------------------------
 *  Copyright (C) 2015-2018 daiteq s.r.o.                http://www.daiteq.com
 *
 *  This program is distributed WITHOUT ANY WARRANTY; without even
 *  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE.
 *
 * -----------------------------------------------------------------------------
 *  Filename    : leon-myuart.c
 *  Authors     : Martin Danek
 *  Description : leon2 uart I/O routines
 *  Release     :
 *  Version     : 1.0
 *  Date        : 10.05.2018
 * -----------------------------------------------------------------------------
 */


#include "leon-myuart.h"


void delay(int i)
{
#ifndef SIM
int k = 0, j = 0;
for(k = 0; k < i; k++)
{
for(j = 0; j < 40; j++);
__asm__ volatile ("\t nop\n");
}
#endif
}

/* ***************** */
/*  UART ROUTINES    */
/*                   */

void init_uart(void) {
  cpu_reg_write(APBPIO_DIRECTION,DIRECTION_UARTS);
  cpu_reg_write(APBUART1_PRESCALER,SCALER_RELOAD_VALUE);
  cpu_reg_write(APBUART1_CONTROL,ENABLE_RX|ENABLE_TX);
}

void m_putchar(unsigned char s) {
int status = 0;
  while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_TH)==0) {
    delay(10);
    ;
  }
  cpu_reg_write(APBUART1_DATA,s);
  while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_TH)==0) {
    delay(10);
    ;
  }
}

unsigned char m_getchar(void) {
int status = 0;
  while ((status=(cpu_reg_read(APBUART1_STATUS))&STAT_DR)==0) {
    delay(10);
      ;
  }
  return cpu_reg_read(APBUART1_DATA);
}



void m_print(unsigned char* s) {
unsigned cnt=200;
unsigned char *l;
  l=s;
  while ((cnt>0)&&(*l!='\0')) {
    if (*l=='\n') {
//       m_putchar(0x0D);
      m_putchar(0x0A);
    }
    else {
      m_putchar(*l);
    }
    l++;
    cnt--;
  }
}


void i_print(int i) {
unsigned char buf[22];
unsigned idx=20;
unsigned neg=0;
  buf[21]='\0';
//  buf[20]='\n';
  if (i==0) {
    buf[idx--]='0';
  }
  else {
    if (i<0) {
      neg=1;
      i=-i;
    }
    while ((i>0)&&(idx>0)) {
      buf[idx--]='0'+(i%10);
      i=i/10;
    }
    if (neg)
      buf[idx--]='-';
  }
  buf[idx]=' ';
  m_print(&buf[idx+1]);
}

void i_hexprint(unsigned i) {
unsigned char buf[22];
unsigned idx=20;
unsigned char dgt;
  buf[21]='\0';
//  buf[20]='\n';
  if (i==0) {
    buf[idx--]='0';
  }
  else {
    while ((i>0)&&(idx>0)) {
      dgt=(i%16);
      if (dgt>9)
        buf[idx--]='A'+dgt-10;
      else
        buf[idx--]='0'+dgt;
      i=i/16;
    }
  }
  if (idx==19)
    buf[idx--]='0';
  buf[idx]=' ';
  m_print(&buf[idx]);
}

unsigned i_conv(char *s) {
  unsigned val=0;
  unsigned i=0;
  while (*(s+i)!='\0') {
    val*=10;
    val+=*(s+i)-'0';
    i++;
  }
  return val;
}

unsigned i_hexconv(char *s) {
  unsigned val=0;
  unsigned i=0;
  while (*(s+i)!='\0') {
    val*=16;
    if ((*(s+i)>='0')&&(*(s+i)<='9'))
      val+=*(s+i)-'0';
    else if ((*(s+i)>='A')&&(*(s+i)<='F'))
      val+=*(s+i)-'A'+10;
    else if ((*(s+i)>='a')&&(*(s+i)<='f'))
      val+=*(s+i)-'a'+10;
    i++;
  }
  return val;
}

unsigned getval(unsigned char* s, unsigned base) {
  char str[25];
  char *p_s;
  unsigned i=0;
  unsigned val=0;
  p_s=str;
  m_print(s);
  do {
    str[i++]=m_getchar();
  } while ((str[i-1]!=0x0D)&&(str[i-1]!=0x0A)&&(i<25));
  str[i-1]='\0';
  if (base==16) {
    val=i_hexconv(p_s);
    i_hexprint(val);
  }
  else {
    val=i_conv(p_s);
    i_print(val);
  }
  m_print("\n");
  return val;
}

void dumpMem(unsigned count, void *address, unsigned len) {
unsigned i,j;

  for (i=0;i<len;i++) {
    if (i%16==0) {
      m_print("\nDUMP");
      i_print(count);
      m_print(": ");
      i_hexprint((unsigned)address+i);
    }
    i_hexprint(*((unsigned char*)address+i));
  }
  m_print("\nDUMP DONE\n");
}

void dataError(void* a, unsigned sz, unsigned i, unsigned expected) {
    m_print("ADDR: ");i_hexprint((unsigned)(a+i*sz));
    m_print(" EXPECTED ");i_hexprint(expected);
    m_print(" ACTUAL ");i_hexprint(*((unsigned*)a+i));
    m_print("\n");
}

/* ***************** */
/*  TIMER ROUTINES   */
/*                   */

#ifdef USE_BSP_INTERRUPTS
  extern volatile unsigned int _tmrcnt;
#endif

void init_timer(void) {
#ifdef USE_BSP_INTERRUPTS
  _tmrcnt = 0;
#endif
  cpu_reg_write(APBTIMER1_CONTROL, TMR_DISABLE);
  cpu_reg_write(APBPRESCALER_RELOAD, TMR_PRESCALER_VALUE);
  cpu_reg_write(APBTIMER1_RELOAD, TMR_RELOAD_VALUE); //TIMER_RELOAD_VALUE);
  cpu_reg_write(APBTIMER1_COUNTER, 0);
#if ((USED_BSP==BSP_GR712RC) || (USED_BSP==BSP_GR740))
  cpu_reg_write(APBTIMER_CONFIG, TIMER_INIT);
#endif
#ifdef USE_BSP_INTERRUPTS
#if (USED_BSP==BSP_GR740)
  cpu_reg_write(APBINTCTRL_LEVEL, 0x2); // set IRQ1 level high
  cpu_reg_write(APBINTCTRL_CSEL, 0x01110000); // connect CPU0 to ICTL0, other CPUs to ICTL1
  cpu_reg_write(APBINTCTRL_CTL, 0x1); // lock ICTL assignments
#endif
  cpu_reg_write(APBINTCTRL_CLEAR, 1<<TIMER_IRQ);
  cpu_reg_write(APBINTCTRL_MASK, (1<<TIMER_IRQ) | (1<<(TIMER_IRQ+16)) ); // enable timer interrupt with higher priority
#endif
  cpu_reg_write(APBTIMER1_CONTROL, TMR_RUN);
}

void timer_start(void)
{
  cpu_reg_write(APBTIMER1_CONTROL, TMR_ENABLE | TMR_RELOAD | TMR_IRQEN);
}

void timer_stop(void)
{
  cpu_reg_write(APBTIMER1_CONTROL, TMR_DISABLE);
}

unsigned int clock(void) {
  unsigned int val;
  val=cpu_reg_read(APBTIMER1_COUNTER);
  return TMR_RELOAD_VALUE-val;
}

unsigned int get_time(unsigned int *sec)
{
  unsigned int val;

  // disable timer interrupt to avoid inconsistency
#ifdef USE_BSP_INTERRUPTS
  unsigned int ints;
  ints = cpu_reg_read(APBINTCTRL_MASK);
  cpu_reg_write(APBINTCTRL_MASK, 0);
#endif
  val=cpu_reg_read(APBTIMER1_COUNTER);
#ifdef USE_BSP_INTERRUPTS
  if (sec) *sec = _tmrcnt;
  cpu_reg_write(APBINTCTRL_MASK, ints);
#endif
  val = TMR_RELOAD_VALUE-val;
  return val;
}