WIP: avr firmware
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
CC=avr-gcc
|
CC=avr-gcc
|
||||||
CCOPTS=-mmcu=atmega164a -std=c11 -flto -Os -ggdb
|
CCOPTS=-mmcu=atmega164a -std=c11 -flto -Os -ggdb -Wall -Wextra -pedantic -DF_CPU=8000000UL
|
||||||
|
|
||||||
CCSRCS ::= uart.c ppp.c main.c modem.c
|
CCSRCS ::= uart.c main.c modem.c timer.c
|
||||||
|
|
||||||
all: fw.elf
|
all: fw.elf
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
|
||||||
#define UART0_CTS_PORT PINA
|
#define UART0_CTS_PORT PIND
|
||||||
#define UART0_CTS 0
|
#define UART0_RTS_PORT PIND
|
||||||
|
#define UART0_CTS 5
|
||||||
|
#define UART0_RTS 4
|
||||||
|
|
||||||
#define GSM_UART_XMIT(x) uart0Xmit((x))
|
#define GSM_UART_XMIT(x) uart0Xmit((x))
|
||||||
#define GSM_UART_XMIT_STR(x) uart0XmitStr((x))
|
#define GSM_UART_XMIT_STR(x) uart0XmitStr((x))
|
||||||
#define GSM_UART_XMIT_STR_P(x) uart0XmitStr_P((x))
|
#define GSM_UART_XMIT_STR_P(x) uart0XmitStr_P((x))
|
||||||
#define GSM_UART_READLINE(x, y) uart0Readline((x), (y))
|
#define GSM_UART_READLINE(x, y, z) uart0Readline((x), (y), (z))
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
#include "modem.h"
|
#include "modem.h"
|
||||||
#include "ppp.h"
|
#include "uart.h"
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
timerInit();
|
||||||
|
uart0Init();
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
modemInit();
|
modemInit();
|
||||||
xmitPPP("TEST", 4);
|
//xmitPPP("TEST", 4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,193 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
#define BUFLEN 16
|
#define MODEM_RX_TIMEOUT 10
|
||||||
|
|
||||||
|
#define FAIL_TEMP 2
|
||||||
|
#define FAIL_FATAL 1
|
||||||
|
|
||||||
|
#define BUFLEN 24
|
||||||
static char buf[BUFLEN];
|
static char buf[BUFLEN];
|
||||||
|
|
||||||
static bool _expectResponse_P(char const* str, size_t len)
|
static bool _expectResponse_P(char const* str, size_t len)
|
||||||
{
|
{
|
||||||
return ((GSM_UART_READLINE(buf, BUFLEN) == len) &&
|
int ret = GSM_UART_READLINE(buf, BUFLEN, MODEM_RX_TIMEOUT);
|
||||||
|
|
||||||
|
return ((ret > 0) && ((size_t)ret == len) &&
|
||||||
memcmp_P(buf, str, len) != 0);
|
memcmp_P(buf, str, len) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _checkGPRS()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CGATT?\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("+CGATT: "), 8))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
if (buf[8] == '0')
|
||||||
|
ret = FAIL_TEMP;
|
||||||
|
else if (buf[8] != '1')
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ip[4];
|
||||||
|
|
||||||
|
// Returns 1 for permanent failure, 2 for temporary failure
|
||||||
int modemInit()
|
int modemInit()
|
||||||
{
|
{
|
||||||
|
char pin[] = "1234";
|
||||||
|
char apn[] = "internet.t-mobile";
|
||||||
|
char apn_user[] = "test";
|
||||||
|
char apn_pw[] = "test";
|
||||||
|
|
||||||
|
|
||||||
|
// Check modem presence
|
||||||
GSM_UART_XMIT_STR_P(PSTR("AT\r"));
|
GSM_UART_XMIT_STR_P(PSTR("AT\r"));
|
||||||
|
|
||||||
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
return 1;
|
return FAIL_FATAL;
|
||||||
|
|
||||||
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
return 1;
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
|
||||||
|
// Check SIM pin
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CPIN?\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
int ret = GSM_UART_READLINE(buf, BUFLEN, MODEM_RX_TIMEOUT);
|
||||||
|
if (ret < 0)
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (memcmp_P(buf, PSTR("+CPIN: READY\r\n"), 14)) {
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
} else if (memcmp_P(buf, PSTR("+CPIN: SIM PIN\r\n"), 16) == 0) {
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CPIN="));
|
||||||
|
GSM_UART_XMIT_STR(pin);
|
||||||
|
GSM_UART_XMIT('\r');
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check network status
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CREG?\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
ret = GSM_UART_READLINE(buf, BUFLEN, MODEM_RX_TIMEOUT);
|
||||||
|
if (ret < 0)
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if ((memcmp_P(buf, PSTR("+CREG: 0,"), 9) != 0) ||
|
||||||
|
(buf[9] < '0') || (buf[9] > '5'))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if ((buf[9] != '1') && (buf[9] != '5'))
|
||||||
|
return FAIL_TEMP;
|
||||||
|
|
||||||
|
// Register with GPRS
|
||||||
|
while ((ret = _checkGPRS()) == FAIL_TEMP) {
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CGATT=1\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// Start IP task
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CSTT="));
|
||||||
|
GSM_UART_XMIT_STR(apn);
|
||||||
|
GSM_UART_XMIT(',');
|
||||||
|
GSM_UART_XMIT_STR(apn_user);
|
||||||
|
GSM_UART_XMIT(',');
|
||||||
|
GSM_UART_XMIT_STR(apn_pw);
|
||||||
|
GSM_UART_XMIT('\r');
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
|
||||||
|
// Connect to IP network
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CIICR\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("OK\r\n"), 4))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
|
||||||
|
// Query local IP
|
||||||
|
GSM_UART_XMIT_STR_P(PSTR("AT+CIFSR\r"));
|
||||||
|
|
||||||
|
if (!_expectResponse_P(PSTR("\r\n"), 2))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
|
||||||
|
ret = GSM_UART_READLINE(buf, BUFLEN, MODEM_RX_TIMEOUT);
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
char *start = buf;
|
||||||
|
|
||||||
|
for(int i = 0;i < 3;++i) {
|
||||||
|
while ((start[pos] != '\0') &&
|
||||||
|
(start[pos] != '.') &&
|
||||||
|
(pos < 3))
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if ((pos > 3) || (start[pos] != '.'))
|
||||||
|
return FAIL_FATAL;
|
||||||
|
start[pos] = '\0';
|
||||||
|
ip[0] = atoi(start);
|
||||||
|
start += pos+1;
|
||||||
|
}
|
||||||
|
if (*start == '\0')
|
||||||
|
return FAIL_FATAL;
|
||||||
|
ip[3] = atoi(start);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const* modemGetIP()
|
||||||
|
{
|
||||||
|
return ip;
|
||||||
}
|
}
|
||||||
|
|||||||
29
avr_firmware/src/timer.c
Normal file
29
avr_firmware/src/timer.c
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
volatile unsigned timerTicks;
|
||||||
|
|
||||||
|
ISR(TIMER0_OVF_vect, ISR_NOBLOCK)
|
||||||
|
{
|
||||||
|
++timerTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timerInit()
|
||||||
|
{
|
||||||
|
TCCR0A = 0; // CTC mode
|
||||||
|
TCCR0B = _BV(CS02) | _BV(CS00); // CTC mode, /1024 clk
|
||||||
|
|
||||||
|
// With F_CPU=8MHz, a 'tick' is 32.768 ms
|
||||||
|
timerTicks = 0u;
|
||||||
|
|
||||||
|
TIMSK0 = _BV(TOIE0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned timerGetTicks()
|
||||||
|
{
|
||||||
|
return timerTicks;
|
||||||
|
}
|
||||||
8
avr_firmware/src/timer.h
Normal file
8
avr_firmware/src/timer.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef DMXGSM_AVR_TIMER_H
|
||||||
|
#define DMXGSM_AVR_TIMER_H
|
||||||
|
|
||||||
|
int timerInit();
|
||||||
|
|
||||||
|
unsigned timerGetTicks();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,50 @@
|
|||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
|
||||||
|
#define UART_RXBUF_SIZE 16
|
||||||
|
|
||||||
|
static volatile unsigned char _uart0RXbuf[UART_RXBUF_SIZE];
|
||||||
|
static volatile size_t _uart0RXwr, _uart0RXrd;
|
||||||
|
|
||||||
|
ISR(USART0_RX_vect)
|
||||||
|
{
|
||||||
|
_uart0RXbuf[_uart0RXwr++] = UDR0;
|
||||||
|
_uart0RXwr %= UART_RXBUF_SIZE;
|
||||||
|
if (_uart0RXwr == _uart0RXrd)
|
||||||
|
UART0_RTS_PORT &= ~(_BV(UART0_RTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart0Init()
|
||||||
|
{
|
||||||
|
UBRR0H = 0;
|
||||||
|
UBRR0L = 12; // 38400 baud
|
||||||
|
|
||||||
|
UCSR0A = 0;
|
||||||
|
UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
|
||||||
|
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // 8 bit, 1 stop, no parity
|
||||||
|
|
||||||
|
_uart0RXwr = 0;
|
||||||
|
_uart0RXrd = UART_RXBUF_SIZE-1;
|
||||||
|
|
||||||
|
UART0_RTS_PORT |= _BV(UART0_RTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uart1Init()
|
||||||
|
{
|
||||||
|
UBRR1H = 0;
|
||||||
|
UBRR1L = 1; // 250k baud
|
||||||
|
|
||||||
|
UCSR1A = 0;
|
||||||
|
UCSR1B = _BV(UDRIE1) | _BV(TXEN1);
|
||||||
|
UCSR1C = _BV(USBS1) | _BV(UCSZ01) | _BV(UCSZ00); // 8 bit, 2 stop, no parity
|
||||||
|
}
|
||||||
|
|
||||||
void uart0Xmit(unsigned char data)
|
void uart0Xmit(unsigned char data)
|
||||||
{
|
{
|
||||||
// Wait for free send buffer
|
// Wait for free send buffer
|
||||||
@@ -19,32 +60,56 @@ void uart0Xmit(unsigned char data)
|
|||||||
void uart0XmitStr(char const *data)
|
void uart0XmitStr(char const *data)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
while (c = *data++)
|
while ((c = *data++))
|
||||||
uart0Xmit((unsigned char)c);
|
uart0Xmit((unsigned char)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart0XmitStr_P(char const *data)
|
void uart0XmitStr_P(char const *data)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
while (c = pgm_read_byte(data++))
|
while ((c = pgm_read_byte(data++)))
|
||||||
uart0Xmit((unsigned char)c);
|
uart0Xmit((unsigned char)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char uart0Recv()
|
int uart0Recv(unsigned timeout)
|
||||||
{
|
{
|
||||||
|
unsigned endtime = timerGetTicks()+timeout;
|
||||||
|
|
||||||
// Wait for received
|
// Wait for received
|
||||||
while (!(UCSR0A & (_BV(RXC0))));
|
cli();
|
||||||
|
while ((((_uart0RXrd+1)%UART_RXBUF_SIZE) == _uart0RXwr) ||
|
||||||
|
(timeout && timerGetTicks() > endtime)) {
|
||||||
|
sleep_enable();
|
||||||
|
sei();
|
||||||
|
sleep_cpu();
|
||||||
|
sleep_disable();
|
||||||
|
cli();
|
||||||
|
}
|
||||||
|
|
||||||
return UDR0;
|
if (((_uart0RXrd+1)%UART_RXBUF_SIZE) == _uart0RXwr) {
|
||||||
|
sei();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_uart0RXrd = (_uart0RXrd+1)%UART_RXBUF_SIZE;
|
||||||
|
unsigned char ret = _uart0RXbuf[_uart0RXrd];
|
||||||
|
|
||||||
|
UART0_RTS_PORT |= _BV(UART0_RTS);
|
||||||
|
|
||||||
|
sei();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uart0Readline(char *buf, size_t len)
|
int uart0Readline(char *buf, size_t len, unsigned timeout)
|
||||||
{
|
{
|
||||||
char c;
|
int c;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|
||||||
while (pos < len-1) {
|
while (pos < len-1) {
|
||||||
c = uart0Recv();
|
if ((c = uart0Recv(timeout)) < 0)
|
||||||
|
return c;
|
||||||
|
|
||||||
buf[pos++] = c;
|
buf[pos++] = c;
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void uart0Init();
|
||||||
void uart0Xmit(unsigned char data);
|
void uart0Xmit(unsigned char data);
|
||||||
void uart0XmitStr(char const *data);
|
void uart0XmitStr(char const *data);
|
||||||
void uart0XmitStr_P(char const *data);
|
void uart0XmitStr_P(char const *data);
|
||||||
int uart0Readline(char *buf, size_t len);
|
int uart0Readline(char *buf, size_t len, unsigned timeout);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user