Commit 1441293c authored by Jake Read's avatar Jake Read

add uartport and rb

parent 58b9ea8e
......@@ -45,10 +45,12 @@ C_SRCS += \
../Device_Startup/system_samd51.c \
../main.c \
../pin.c \
../ringbuffer.c \
../sam_ba_cdc.c \
../sam_ba_monitor.c \
../sam_ba_serial.c \
../sam_ba_usb.c
../sam_ba_usb.c \
../uartport.c
PREPROCESSING_SRCS +=
......@@ -65,10 +67,12 @@ Device_Startup/startup_samd51.o \
Device_Startup/system_samd51.o \
main.o \
pin.o \
ringbuffer.o \
sam_ba_cdc.o \
sam_ba_monitor.o \
sam_ba_serial.o \
sam_ba_usb.o
sam_ba_usb.o \
uartport.o
OBJS_AS_ARGS += \
board_driver_serial.o \
......@@ -78,10 +82,12 @@ Device_Startup/startup_samd51.o \
Device_Startup/system_samd51.o \
main.o \
pin.o \
ringbuffer.o \
sam_ba_cdc.o \
sam_ba_monitor.o \
sam_ba_serial.o \
sam_ba_usb.o
sam_ba_usb.o \
uartport.o
C_DEPS += \
board_driver_serial.d \
......@@ -91,10 +97,12 @@ Device_Startup/startup_samd51.d \
Device_Startup/system_samd51.d \
main.d \
pin.d \
ringbuffer.d \
sam_ba_cdc.d \
sam_ba_monitor.d \
sam_ba_serial.d \
sam_ba_usb.d
sam_ba_usb.d \
uartport.d
C_DEPS_AS_ARGS += \
board_driver_serial.d \
......@@ -104,10 +112,12 @@ Device_Startup/startup_samd51.d \
Device_Startup/system_samd51.d \
main.d \
pin.d \
ringbuffer.d \
sam_ba_cdc.d \
sam_ba_monitor.d \
sam_ba_serial.d \
sam_ba_usb.d
sam_ba_usb.d \
uartport.d
OUTPUT_FILE_PATH +=mkrouter-v06.elf
......@@ -143,6 +153,10 @@ LINKER_SCRIPT_DEP+= \
......
......@@ -16,6 +16,8 @@ main.c
pin.c
ringbuffer.c
sam_ba_cdc.c
sam_ba_monitor.c
......@@ -24,3 +26,5 @@ sam_ba_serial.c
sam_ba_usb.c
uartport.c
......@@ -12,6 +12,20 @@
#define HARDWARE_H_
#include "pin.h"
#include "ringbuffer.h"
#include "uartport.h"
// For if-case init
#define HARDWARE_IS_APBA 0
#define HARDWARE_IS_APBB 1
#define HARDWARE_IS_APBC 2
#define HARDWARE_IS_APBD 3
#define HARDWARE_ON_PERIPHERAL_A 0x0
#define HARDWARE_ON_PERIPHERAL_B 0x1
#define HARDWARE_ON_PERIPHERAL_C 0x2
#define HARDWARE_ON_PERIPHERAL_D 0x3
/* USB PINS
......@@ -39,6 +53,10 @@ UP0STLB PB22 (on receive)
UP0STLR PB31 (on transmit)
*/
ringbuffer_t up0rbrx;
ringbuffer_t up0rbtx;
uartport_t up0;
pin_t up0stlb;
pin_t up0stlr;
......@@ -51,6 +69,10 @@ UP1STLB PA20
UP1STLR PA21
*/
ringbuffer_t up1rbrx;
ringbuffer_t up1rbtx;
uartport_t up1;
pin_t up1stlb;
pin_t up1stlr;
......@@ -62,6 +84,10 @@ UP2STLB PB16
UP2STLR PB17
*/
ringbuffer_t up2rbrx;
ringbuffer_t up2rbtx;
uartport_t up2;
pin_t up2stlb;
pin_t up2stlr;
......@@ -73,6 +99,10 @@ UP3STLB PA18
UP3STLR PA19
*/
ringbuffer_t up3rbrx;
ringbuffer_t up3rbtx;
uartport_t up3;
pin_t up3stlb;
pin_t up3stlr;
......@@ -84,6 +114,10 @@ UP4STLB PA14
UP4STLR PA15
*/
ringbuffer_t up4rbrx;
ringbuffer_t up4rbtx;
uartport_t up4;
pin_t up4stlb;
pin_t up4stlr;
......@@ -95,9 +129,16 @@ UP5STLB PB13
UP5STLR PB14
*/
ringbuffer_t up5rbrx;
ringbuffer_t up5rbtx;
uartport_t up5;
pin_t up5stlb;
pin_t up5stlr;
// pointers to uarports
#define NUM_UPS 6
uartport_t *ups[NUM_UPS];
#endif /* HARDWARE_H_ */
\ No newline at end of file
......@@ -69,6 +69,60 @@ void lights_init(void){
pin_set(&up5stlr);
}
void uarts_init(void){
// don't forget to also add the handler
NVIC_EnableIRQ(SERCOM0_0_IRQn);
NVIC_EnableIRQ(SERCOM0_2_IRQn);
// init rbs
rb_init(&up0rbrx);
rb_init(&up0rbtx);
// init uart
up0 = uart_new(SERCOM0, &PORT->Group[0], &up0rbrx, &up0rbtx, 5, 4);
MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0;
uart_init(&up0, 7, SERCOM0_GCLK_ID_CORE, 63018, HARDWARE_ON_PERIPHERAL_D);
// init rbs
rb_init(&up1rbrx);
rb_init(&up1rbtx);
// init rbs
rb_init(&up2rbrx);
rb_init(&up2rbtx);
// init rbs
rb_init(&up3rbrx);
rb_init(&up3rbtx);
// init rbs
rb_init(&up4rbrx);
rb_init(&up4rbtx);
// init rbs
rb_init(&up5rbrx);
rb_init(&up5rbtx);
// now pack all into ups
ups[0] = &up0;
ups[1] = &up1;
ups[2] = &up2;
ups[3] = &up3;
ups[4] = &up4;
ups[5] = &up5;
}
static volatile bool main_b_cdc_enable = false;
int main(void)
......@@ -81,6 +135,9 @@ int main(void)
__enable_irq();
lights_init();
// init uartports
uarts_init();
// pointer to the USB struct in sam_ba_usb.h
P_USB_CDC pCdc;
......@@ -94,22 +151,26 @@ int main(void)
/* Replace with your application code */
while (1)
{
// waits for config to config
if(pCdc->IsConfigured(pCdc) != 0){
main_b_cdc_enable = true;
pin_clear(&stlUsb);
}
uint8_t testUart[3] = {12,24,48};
// if config is config, and port is opened
if(main_b_cdc_enable){
sam_ba_monitor_init(SAM_BA_INTERFACE_USBCDC);
// loops on this
while(1){
sam_ba_monitor_run();
// @ HERE: understand how this /\ runs, looks through buffer etc...
// do the same for (1) bytes -> uart
// (2) for packet searching
for(int i = 0; i < NUM_UPS; i ++){
while(!rb_empty(up0.rbrx)){
uart_sendchar_buffered(&up0, rb_get(up0.rbrx));
}
}
//uart_sendchars_buffered(&up0, &testUart, 3);
// apaport loops
}
}
......@@ -138,3 +199,11 @@ void SysTick_Handler(void){
*/
// monitor_sys_tick
}
void SERCOM0_0_Handler(void){
uart_txhandler(&up0);
}
void SERCOM0_2_Handler(void){
uart_rxhandler(&up0);
}
\ No newline at end of file
......@@ -195,6 +195,12 @@
<Compile Include="pin.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="ringbuffer.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="ringbuffer.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="sam_ba_cdc.c">
<SubType>compile</SubType>
</Compile>
......@@ -219,6 +225,12 @@
<Compile Include="sam_ba_usb.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="uartport.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="uartport.h">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="Device_Startup\" />
......
/*
* ringbuffer.c
*
* Created: 2/7/2018 11:39:44 AM
* Author: Jake
*/
#include "ringbuffer.h"
uint8_t rb_init(ringbuffer_t *rb){
rb->size = RINGBUFFER_SIZE; // stuck with this, due to not having malloc, wall of skill
//rb->buffer = malloc(size);
rb_reset(rb);
return 1;
}
uint8_t rb_reset(ringbuffer_t *rb){
if(rb){
rb->head = 0;
rb->tail = 0;
return 1;
} else {
return 0;
}
}
uint8_t rb_empty(ringbuffer_t *rb){
return (rb->head == rb->tail);
}
uint8_t rb_full(ringbuffer_t *rb){
// read from tail, update at head
// if head is 'just behind' tail (in ring) we have no extra space: the
return ((rb->head + 1) % rb->size) == rb->tail;
}
uint8_t rb_freespace(ringbuffer_t *rb){
if(rb->head >= rb->tail){
return rb->size - (rb->head - rb->tail);
} else {
return rb->tail - rb->head - 1;
}
}
uint8_t rb_putchar(ringbuffer_t *rb, uint8_t data){
rb->buffer[rb->head] = data;
rb->head = (rb->head + 1) % rb->size; // increment and loop about
return 1;
}
uint8_t rb_putdata(ringbuffer_t *rb, uint8_t *data, uint8_t size){
/*
if(rb_freespace(rb) >= size){
// rb_freespace, not working?
return 0;
} else {
*/
for(int i = 0; i < size; i ++){
rb_putchar(rb, data[i]);
}
return 1;
//}
}
uint8_t rb_get(ringbuffer_t *rb){
uint8_t data = rb->buffer[rb->tail];
rb->tail = (rb->tail + 1) % rb->size;
return data;
}
/*
* ringbuffer.h
*
* Created: 2/7/2018 11:39:54 AM
* Author: Jake
*/
#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
/*
a ringbuffer,
s/o https://github.com/dhess/c-ringbuf
s/o https://embeddedartistry.com/blog/2017/4/6/circular-buffers-in-cc
s/o https://www.downtowndougbrown.com/2013/01/microcontrollers-interrupt-safe-ring-buffers/
*/
#include "sam.h"
#include <stdlib.h> // for size_t
#define RINGBUFFER_SIZE 256
typedef struct{
uint8_t buffer[256]; // static! big enough
size_t head;
size_t tail;
size_t size;
} ringbuffer_t;
uint8_t rb_init(ringbuffer_t *rb);
uint8_t rb_reset(ringbuffer_t *rb);
uint8_t rb_empty(ringbuffer_t *rb);
uint8_t rb_full(ringbuffer_t *rb);
uint8_t rb_freespace(ringbuffer_t *rb);
uint8_t rb_putchar(ringbuffer_t *rb, uint8_t data);
uint8_t rb_putdata(ringbuffer_t *rb, uint8_t *data, uint8_t size);
uint8_t rb_get(ringbuffer_t *rb);
#endif /* RINGBUFFER_H_ */
\ No newline at end of file
......@@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "sam_ba_cdc.h"
//#include "board_driver_led.h"
#include "hardware.h"
const char RomBOOT_Version[] = SAM_BA_VERSION;
const char RomBOOT_ExtendedCapabilities[] = "[Arduino:XYZ]";
......@@ -277,19 +279,33 @@ static void sam_ba_monitor_loop(void)
{
// get bytes, handle..
length = sam_ba_getdata(ptr_monitor_if, data, SIZEBUFMAX);
pin_clear(&stlPacket);
if(length > 0 && !usbComOpen){
usbComOpen = 1;
pin_clear(&stlUsb);
}
// reply
sam_ba_putdata(ptr_monitor_if, data, length);
// have to implement APA code here? and watch for multipackets?
for(int i = 0; i < length; i ++, ptr++){
// apa
}
pin_set(&stlPacket);
// dirt nasty heartbeat
/*
if(!(tick % 100000)){
sam_ba_putdata(ptr_monitor_if, &data_out, 3);
}
tick ++;
*/
}
void sam_ba_port_put_data(uint8_t *data, uint32_t length){
sam_ba_putdata(ptr_monitor_if, data, length);
}
void sam_ba_monitor_sys_tick(void)
......@@ -308,6 +324,7 @@ void sam_ba_monitor_sys_tick(void)
*/
void sam_ba_monitor_run(void)
{
/*
uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
PAGE_SIZE = pageSizes[NVMCTRL->PARAM.bit.PSZ];
PAGES = NVMCTRL->PARAM.bit.NVMP;
......@@ -315,8 +332,7 @@ void sam_ba_monitor_run(void)
ptr_data = NULL;
command = 'z';
while (1)
{
sam_ba_monitor_loop();
}
*/
sam_ba_monitor_loop();
}
......@@ -57,6 +57,8 @@ void sam_ba_monitor_sys_tick(void);
*/
void sam_ba_monitor_run(void);
void sam_ba_port_put_data(uint8_t *data, uint32_t length);
/**
* \brief
*
......
/*
* uartport.c
*
* Created: 2/6/2018 10:48:26 AM
* Author: Jake
*/
#include "uartport.h"
#include "hardware.h"
uartport_t uart_new(Sercom *com, PortGroup *port, ringbuffer_t *rbrx, ringbuffer_t *rbtx, uint32_t rx_pin, uint32_t tx_pin){
uartport_t uart;
// pointers to com and port
uart.com = com;
uart.port = port;
// add ringbuffers
uart.rbrx = rbrx;
uart.rbtx = rbtx;
// pins
uart.pinrx = rx_pin;
uart.pinrx_bm = (uint32_t)(1 << rx_pin);
uart.pintx = tx_pin;
uart.pintx_bm = (uint32_t)(1 << tx_pin);
return uart;
}
void uart_init(uartport_t *uart, uint32_t gclknum, uint32_t gclkidcore, uint16_t baud, uint32_t peripheral){
// rx pin setups
uart->port->DIRCLR.reg = uart->pinrx_bm;
uart->port->PINCFG[uart->pinrx].bit.PMUXEN = 1;
if(uart->pinrx % 2){ // yes if odd
uart->port->PMUX[uart->pinrx >> 1].reg |= PORT_PMUX_PMUXO(peripheral);
} else {
uart->port->PMUX[uart->pinrx >> 1].reg |= PORT_PMUX_PMUXE(peripheral);
}
// tx pin setups
uart->port->DIRSET.reg = uart->pintx_bm;
uart->port->PINCFG[uart->pintx].bit.PMUXEN = 1;
if(uart->pintx % 2){ // yes if odd
uart->port->PMUX[uart->pintx >> 1].reg |= PORT_PMUX_PMUXO(peripheral);
} else {
uart->port->PMUX[uart->pintx >> 1].reg |= PORT_PMUX_PMUXE(peripheral);
}
// unmask the clock
// -> have to do this manually b/c unfavourable api
GCLK->GENCTRL[gclknum].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) | GCLK_GENCTRL_GENEN;
while(GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(gclknum));
GCLK->PCHCTRL[gclkidcore].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclknum);
// now the sercom
while(uart->com->USART.SYNCBUSY.bit.ENABLE);
uart->com->USART.CTRLA.bit.ENABLE = 0;
while(uart->com->USART.SYNCBUSY.bit.SWRST);
uart->com->USART.CTRLA.bit.SWRST = 1;
while(uart->com->USART.SYNCBUSY.bit.SWRST);
while(uart->com->USART.SYNCBUSY.bit.SWRST || SERCOM5->USART.SYNCBUSY.bit.ENABLE);
uart->com->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(1) | SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_RXPO(1) | SERCOM_USART_CTRLA_TXPO(0);
while(uart->com->USART.SYNCBUSY.bit.CTRLB);
uart->com->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0);
/*
BAUD = 65536*(1-S*(fBAUD/fref))
where S is samples per bit, 16 for async uart
where fBAUD is the rate that you want
where fref is the peripheral clock from GCLK, in this case (and most) 48MHz
*/
uart->com->USART.BAUD.reg = baud;
while(uart->com->USART.SYNCBUSY.bit.ENABLE);
uart->com->USART.CTRLA.bit.ENABLE = 1;
uart->com->USART.INTENSET.bit.RXC = 1; // set receive interrupt on, see 34.6.4.2
}
void uart_sendchar_polled(uartport_t *uart, uint8_t data){
while(!uart->com->USART.INTFLAG.bit.DRE);
uart->com->USART.DATA.reg = data;
}
void uart_sendchar_buffered(uartport_t *uart, uint8_t data){
rb_putchar(uart->rbtx, data); // dump it in there
uart->com->USART.INTENSET.bit.DRE = 1; // set up the volley
}
void uart_sendchars_buffered(uartport_t *uart, uint8_t *data, uint8_t length){
rb_putdata(uart->rbtx, data, length);
uart->com->USART.INTENSET.bit.DRE = 1;
}
void uart_rxhandler(uartport_t *uart){
uint8_t data = uart->com->USART.DATA.reg;
rb_putchar(uart->rbrx, data);
}
void uart_txhandler(uartport_t *uart){
if(!rb_empty(uart->rbtx)){
uart->com->USART.DATA.reg = rb_get(uart->rbtx);
} else {
uart->com->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE;
}
}
\ No newline at end of file