NXP LPC1114 UART no funciona después del reinicio

Estoy construyendo un circuito simple con LPC1114 para hacer una aplicación "hola mundo" usando UART. Tratando de escribir todo el código desde cero, para tener una mejor comprensión de lo que está sucediendo.

Mi problema es que UART solo funciona después de flashear (es decir, cuando lpc21isp le pide a MCU que comience a ejecutar el código). El mismo código no funciona si se reinicia MCU.

Aquí está el código que estoy usando:

void platform_uart_setup(uint32_t baud_rate) // 9600
{
  // Make sure UART IRQ is disabled
  NVIC_DisableIRQ(UART_IRQn);

  // Setup pin 1_6 as RXD
  LPC_IOCON->PIO1_6 &= ~0x07;
  LPC_IOCON->PIO1_6 |= 0x01;

  // Setup pin 1_7 as TXD
  LPC_IOCON->PIO1_7 &= ~0x07;
  LPC_IOCON->PIO1_7 |= 0x01;

  // Enable & configure UART clock
  LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);
  LPC_SYSCON->UARTCLKDIV = 0x1;

  // Setup format: 8N1, enable access to divisor latches
  LPC_UART->LCR = 0x83;

  // Setup baud rate, which is based on system clock
  uint32_t Fdiv = platform_clock // take cpu clock (12000000 in this case)
      / LPC_SYSCON->SYSAHBCLKDIV // divide by ABH clock
      / LPC_SYSCON->UARTCLKDIV // divide further by UART clock
      / 16 // divisor latch is 16x the desired baud rate
      / baud_rate;

  LPC_UART->DLM = Fdiv / 256;
  LPC_UART->DLL = Fdiv % 256;

  LPC_UART->FDR = 0x00 | (1 << 4) | 0;

  // Enable and reset FIFOs
  LPC_UART->FCR = 0x07;

  // Disable access to divisor latches
  LPC_UART->LCR = 0x03;

  // Read to reset LSR
  volatile uint32_t unused = LPC_UART->LSR;

  // Make sure there's no data
  while(( LPC_UART->LSR & (0x20|0x40)) != (0x20|0x40) )
    ;
  while( LPC_UART->LSR & 0x01 ) {
    unused = LPC_UART->RBR;
  }

  // Enable UART IRQ
  NVIC_EnableIRQ(UART_IRQn);

  // We don't care about interrupts for now
  LPC_UART->IER = 0;
}

void platform_uart_putc(const char c)
{
  while( !(LPC_UART->LSR & 0x20) )
    ;
  LPC_UART->THR = c;
}

Después del reinicio, no hay absolutamente ningún cambio de señal en el pin TXD.

¿Puedes mostrar el circuito? Esto puede deberse a un puente establecido en el arranque desde 'x' en oposición al arranque desde 'y'
Bueno, si sumo algunos leds y los parpadeo, parpadea platform_uart_putc, entonces el código se ejecuta. El circuito es bastante simple, es solo RXD/TXD a FTDI, y dos botones para restablecer y pin de entrada del cargador de arranque 1.1.
muchas gracias. No sé cómo, pero por proyectos dejó de funcionar después de un tiempo. UART simplemente no envió nada. No sé por qué IOCON estaba deshabilitado para todo. ¡Lo agregué en System init y todo se resolvió!
Si está usando, system_LPC11xx.htambién puede usar SystemCoreClockdespués de llamar SystemInity SystemCoreClockUpdate. Contiene la frecuencia del reloj central (aunque con una configuración predeterminada probablemente 12000000).

Respuestas (1)

Creo que olvidó habilitar el reloj para IOCON antes de configurar los pines para el uso de UART, por lo tanto, esas asignaciones no tienen efecto. Pero después de una carga de arranque, los pines ya están configurados para UART, por lo que todo funciona.

Insertar

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16); // enable IOCON

después de la configuración de IRQ, antes de configurar los pines.

PD: mi biblioteca bmptk es compatible con LPC1114. Está en C ++, pero puede echar un vistazo a la configuración de pines GPIO (¡y la inicialización de UART!), Compruebe targett/cortex/lpc1114fn28.h y la inicialización del temporizador en targets/cortex/lpc1114.cpp

No puedo encontrar lpc1114.cppen su BMPTK. Una búsqueda de LPC_UARTno arrojó nada. Otra pregunta, ¿podría indicarme dónde dice el manual de usuario dónde IOCONse debe habilitar?
IIRC que no se menciona en la descripción de los periféricos en sí, solo en la descripción del registro SYSCON.