Port, Buffer, DigitalInOut, and Spi (master) works.

pull/159/head
tkuyucu 2013-12-02 16:33:08 +01:00
parent 820e0473f6
commit 685274563e
9 changed files with 450 additions and 36 deletions

View File

@ -26,6 +26,13 @@ typedef enum {
UART_0 = (int)NRF_UART0_BASE
} UARTName;
typedef enum {
SPI_0 = (int)NRF_SPI0_BASE,
SPI_1 = (int)NRF_SPI1_BASE,
SPIS = (int)NRF_SPIS1_BASE
} SPIName;
#define STDIO_UART_TX TX_PIN_NUMBER
#define STDIO_UART_RX RX_PIN_NUMBER
#define STDIO_UART UART_0
@ -75,11 +82,6 @@ typedef enum {
DAC_0 = 0
} DACName;
typedef enum {
SPI_0 = (int)SPI0_BASE,
SPI_1 = (int)SPI1_BASE,
} SPIName;
*/
#ifdef __cplusplus
}

View File

@ -27,28 +27,77 @@ typedef enum {
PIN_OUTPUT
} PinDirection;
#define PORT_SHIFT 12
#define PORT_SHIFT 3
typedef enum {
LED_START = 18,
LED_STOP = 19,
p0=0,
p1=1,
p2=2,
p3=3,
p4=4,
p5=5,
p6=6,
p7=7,
p8=8,
p9=9,
p10=10,
p11=11,
p12=12,
p13=13,
p14=14,
p15=15,
p16=16,
p17=17,
p18=18,
p19=19,
p20=20,
p21=21,
p22=22,
p23=23,
p24=24,
p25=25,
p26=26,
p27=27,
p28=28,
p29=29,
p30=30,
p31=31,
LED_START = p18,
LED_STOP = p19,
LED1 = LED_START,
LED2 = LED_STOP,
LED3 = LED_START,
LED4 = LED_STOP,
BUTTON_START = 16,
BUTTON_STOP = 17,
BUTTON_START = p16,
BUTTON_STOP = p17,
BUTTON0 = BUTTON_START,
BUTTON1 = BUTTON_STOP,
// USB Pins
RX_PIN_NUMBER = 11,
TX_PIN_NUMBER = 9,
CTS_PIN_NUMBER = 10,
RTS_PIN_NUMBER = 8,
RX_PIN_NUMBER = p11,
TX_PIN_NUMBER = p9,
CTS_PIN_NUMBER = p10,
RTS_PIN_NUMBER = p8,
USBTX = TX_PIN_NUMBER,
USBRX = RX_PIN_NUMBER,
SPI_PSELSCK0 = p31,
SPI_PSELMOSI0 = p20,
SPI_PSELMISO0 = p22,
SPI_PSELSS0 = p30,
SPI_PSELSCK1 = p29,
SPI_PSELMOSI1 = p21,
SPI_PSELMISO1 = p23,
SPI_PSELSS1 = p28,
SPIS_PSELMISO = p12,
SPIS_PSELSS = p13,
SPIS_PSELMOSI = p14,
SPIS_PSELSCK = p15,
// Not connected
NC = (int)0xFFFFFFFF
} PinName;

View File

@ -21,10 +21,10 @@ extern "C" {
#endif
typedef enum {
Port0 = 0,
Port1 = 1,
Port2 = 2,
Port3 = 3,
Port0 = 0, //GPIO pins 0-7
Port1 = 1, //GPIO pins 8-15
Port2 = 2, //GPIO pins 16-22
Port3 = 3, //GPIO pins 24-31
} PortName;
#ifdef __cplusplus

View File

@ -16,9 +16,9 @@
#ifndef MBED_DEVICE_H
#define MBED_DEVICE_H
#define DEVICE_PORTIN 0
#define DEVICE_PORTOUT 0
#define DEVICE_PORTINOUT 0
#define DEVICE_PORTIN 1
#define DEVICE_PORTOUT 1
#define DEVICE_PORTINOUT 1
#define DEVICE_INTERRUPTIN 0
@ -30,8 +30,8 @@
#define DEVICE_I2C 0
#define DEVICE_I2CSLAVE 0
#define DEVICE_SPI 0
#define DEVICE_SPISLAVE 0
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 1
#define DEVICE_CAN 0

View File

@ -48,8 +48,19 @@ void gpio_mode(gpio_t *obj, PinMode mode) {
void gpio_dir(gpio_t *obj, PinDirection direction) {
switch (direction) {
case PIN_INPUT : *obj->reg_dir &= ~obj->mask; break;
case PIN_OUTPUT: *obj->reg_dir |= obj->mask; break;
case PIN_INPUT :// *obj->reg_dir &= ~obj->mask;
NRF_GPIO->PIN_CNF[obj->pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
break;
case PIN_OUTPUT: //*obj->reg_dir |= obj->mask;
NRF_GPIO->PIN_CNF[obj->pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
break;
}
}
/*

View File

@ -30,6 +30,20 @@ struct serial_s {
int index;
};
struct spi_s {
NRF_SPI_Type *spi;
NRF_SPIS_Type *spis;
};
struct port_s {
__IO uint32_t *reg_cnf;
__IO uint32_t *reg_out;
__I uint32_t *reg_in;
PortName port;
uint32_t mask;
};
/*
struct gpio_irq_s {
uint32_t port;
@ -37,14 +51,6 @@ struct gpio_irq_s {
uint32_t ch;
};
struct port_s {
__IO uint32_t *reg_dir;
__IO uint32_t *reg_out;
__I uint32_t *reg_in;
PortName port;
uint32_t mask;
};
struct pwmout_s {
__IO uint32_t *MOD;
__IO uint32_t *CNT;
@ -64,9 +70,6 @@ struct i2c_s {
I2C_Type *i2c;
};
struct spi_s {
SPI_Type *spi;
};
*/
#include "gpio_object.h"

View File

@ -25,5 +25,12 @@ void pin_mode(PinName pin, PinMode mode) {
uint32_t pin_number = (uint32_t)pin;
NRF_GPIO->PIN_CNF[pin_number] |= (mode<<GPIO_PIN_CNF_PULL_Pos);
}
/*
NRF_GPIO->PIN_CNF[pin_number] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (mode << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos);*/

View File

@ -0,0 +1,86 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "port_api.h"
#include "pinmap.h"
#include "gpio_api.h"
PinName port_pin(PortName port, int pin_n) {
return (PinName)((port << PORT_SHIFT) | pin_n);
}
void port_init(port_t *obj, PortName port, int mask, PinDirection dir) {
obj->port = port;
obj->mask = mask;
obj->reg_out = &NRF_GPIO->OUT;
obj->reg_in = &NRF_GPIO->IN;
obj->reg_cnf = NRF_GPIO->PIN_CNF;
uint32_t i;
// The function is set per pin: reuse gpio logic
/* for (i=0; i<32; i++) {
if (obj->mask & (1<<i)) {
gpio_set(port_pin(obj->port, i));
}
}*/
port_dir(obj, dir);
}
void port_mode(port_t *obj, PinMode mode) {
uint32_t i;
// The mode is set per pin: reuse pinmap logic
for (i=0; i<8; i++) {
if (obj->mask & (1<<i)) {
pin_mode(port_pin(obj->port, i), mode);
}
}
}
void port_dir(port_t *obj, PinDirection dir) {
int i;
switch (dir) {
case PIN_INPUT : //*((volatile uint8_t*)(obj->reg_dir)+ (uint8_t)obj->port) &= ~obj->mask;
for (i=0; i<8; i++) {
if (obj->mask & (1<<i)) {
obj->reg_cnf[port_pin(obj->port, i)] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
}
}
break;
case PIN_OUTPUT:// *((volatile uint8_t*)(obj->reg_dir)+ (uint8_t)obj->port) |= obj->mask;
for (i=0; i<8; i++) {
if (obj->mask & (1<<i)) {
obj->reg_cnf[port_pin(obj->port, i)] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
}
}
break;
}
}
void port_write(port_t *obj, int value) {
*((volatile uint8_t*)(obj->reg_out)+(uint8_t)obj->port) = value;
}
int port_read(port_t *obj) {
return (*((const volatile uint8_t*)(obj->reg_in) + obj->port));
}

View File

@ -0,0 +1,256 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#include <math.h>
#include "spi_api.h"
#include "cmsis.h"
#include "pinmap.h"
#include "error.h"
static const PinMap PinMap_SPI_SCLK[] = {
{SPI_PSELSCK0 , SPI_0, 0x01},
{SPI_PSELSCK1, SPI_1, 0x02},
{SPIS_PSELSCK, SPIS, 0x03},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MOSI[] = {
{SPI_PSELMOSI0 , SPI_0, 0x01},
{SPI_PSELMOSI1, SPI_1, 0x02},
{SPIS_PSELMOSI, SPIS, 0x03},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_MISO[] = {
{SPI_PSELMISO0 , SPI_0, 0x01},
{SPI_PSELMISO1, SPI_1, 0x02},
{SPIS_PSELMISO, SPIS, 0x03},
{NC , NC , 0}
};
static const PinMap PinMap_SPI_SSEL[] = {
{SPIS_PSELSS, SPIS, 0x03},
{NC , NC , 0}
};
// {SPI_PSELSS0 , SPI_0, 0x01},
#define SPIS_MESSAGE_SIZE 4
volatile uint8_t m_tx_buf[SPIS_MESSAGE_SIZE] = {0,0,0,0};
volatile uint8_t m_rx_buf[SPIS_MESSAGE_SIZE] = {5,5,5,5};
static inline int ssp_disable(spi_t *obj);
static inline int ssp_enable(spi_t *obj);
void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
// determine the SPI to use
SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
SPIName spi = (SPIName)pinmap_merge(spi_data, spi_cntl);
//SPIName
if(ssel==NC){
obj->spi = (NRF_SPI_Type*)spi;
obj->spis = (NRF_SPIS_Type*)NC;
}
else{
obj->spi = (NRF_SPI_Type*)NC;
obj->spis = (NRF_SPIS_Type*)spi;
}
if ((int)obj->spi == NC && (int)obj->spis == NC) {
error("SPI pinout mapping failed");
}
// enable power and clocking ?
// pin out the spi pins
if (ssel != NC) {//slave
obj->spis->POWER=1;
NRF_GPIO->DIR &= ~(1<<mosi);
NRF_GPIO->DIR &= ~(1<<miso);
NRF_GPIO->DIR &= ~(1<<sclk);
NRF_GPIO->DIR &= ~(1<<ssel);
obj->spis->PSELMOSI = mosi;
obj->spis->PSELMISO = miso;
obj->spis->PSELSCK = sclk;
obj->spis->PSELCSN = ssel;
obj->spis->EVENTS_END=0;
obj->spis->EVENTS_ACQUIRED=0;
obj->spis->MAXRX=SPIS_MESSAGE_SIZE;
obj->spis->MAXTX=SPIS_MESSAGE_SIZE;
obj->spis->TXDPTR = (uint32_t)&m_tx_buf[0];
obj->spis->RXDPTR = (uint32_t)&m_rx_buf[0];
}
else{//master
obj->spi->POWER=1;
NRF_GPIO->DIR |= (1<<mosi);
obj->spi->PSELMOSI = mosi;
NRF_GPIO->DIR |= (1<<sclk);
obj->spi->PSELSCK = sclk;
NRF_GPIO->DIR &= ~(1<<miso);
obj->spi->PSELMISO = miso;
obj->spi->EVENTS_READY = 0U;
}
// set default format and frequency
if (ssel == NC) {
spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
spi_frequency(obj, 1000000);
} else {
spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
}
}
void spi_free(spi_t *obj) {}
static inline void spi_disable(spi_t *obj, int slave) {
if(slave){
obj->spis->ENABLE = (SPIS_ENABLE_ENABLE_Disabled << SPIS_ENABLE_ENABLE_Pos);
}
else{
obj->spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
}
}
static inline void spi_enable(spi_t *obj, int slave) {
if(slave){
obj->spis->ENABLE = (SPIS_ENABLE_ENABLE_Enabled << SPIS_ENABLE_ENABLE_Pos);
}
else{
obj->spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
}
}
void spi_format(spi_t *obj, int bits, int mode, int slave) {
uint32_t config_mode;
spi_disable(obj,slave);
if (bits != 8) {
error("Only 8bits SPI supported");
}
switch (mode)
{
case 0:
config_mode = (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
break;
case 1:
config_mode = (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);
break;
case 2:
config_mode = (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
break;
case 3:
config_mode = (SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos) | (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos);
break;
default:
error("SPI format error");
break;
}
//default to msb first
if(slave){
obj->spis->CONFIG = (config_mode | (SPI_CONFIG_ORDER_MsbFirst << SPI_CONFIG_ORDER_Pos));
}
else{
obj->spi->CONFIG = (config_mode | (SPI_CONFIG_ORDER_MsbFirst << SPI_CONFIG_ORDER_Pos));
}
spi_enable(obj,slave);
}
void spi_frequency(spi_t *obj, int hz) {
if((int)obj->spi==NC)
return;
spi_disable(obj,0);
switch(hz)
{
case 125000: obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL); break;
case 250000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 1 ); break;
case 500000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 2 ); break;
case 1000000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 3 ); break;
case 2000000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 4 ); break;
case 4000000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 5 ); break;
case 8000000:obj->spi->FREQUENCY = (uint32_t)( 0x02000000UL << 6 ); break;
default:error("Couldn't setup requested SPI frequency"); return;
}
spi_enable(obj,0);
}
static inline int spi_readable(spi_t *obj) {
return (obj->spi->EVENTS_READY == 1);
}
static inline int spi_writeable(spi_t *obj) {
return (obj->spi->EVENTS_READY == 0);
}
/*static inline void spi_write(spi_t *obj, int value) {
obj->spi->DR = value;
}*/
static inline int spi_read(spi_t *obj) {
while (!spi_readable(obj)); //timeout ?
obj->spi->EVENTS_READY =0;
return (int)obj->spi->RXD;
}
int spi_master_write(spi_t *obj, int value) {
while (!spi_writeable(obj));
obj->spi->TXD = (uint32_t)value;
return spi_read(obj);
}
static inline int spis_readable(spi_t *obj) {
}
static inline int spis_writeable(spi_t *obj) {
return (obj->spis->EVENTS_ACQUIRED==1);
}
int spi_slave_receive(spi_t *obj) {
//return (((NRF_GPIO->IN >> obj->spis->PSELCSN) & 1UL)==0);
int res = (obj->spis->EVENTS_END==1);
obj->spis->EVENTS_END=0;
return res;
//return (obj->spis->EVENTS_ACQUIRED==1);
};
int spi_slave_read(spi_t *obj) {
//&m_rx_buf[0] = obj->spis->RXDPTR;
int val = m_rx_buf[3]<<24 | m_rx_buf[2] <<16 | m_rx_buf[1] <<8 | m_rx_buf[0];
return val;//m_rx_buf[3];//obj->spis->RXDPTR;//
}
void spi_slave_write(spi_t *obj, int value) {
obj->spis->TASKS_ACQUIRE=1;
while (!spis_writeable(obj)) ;
//obj->spis->TXDPTR = value;
m_tx_buf[0]= value & 0xFF;
m_tx_buf[1]= value & 0xFF00;
m_tx_buf[2]= value & 0xFF0000;
m_tx_buf[3]= value & 0xFF000000;
obj->spis->TXDPTR = (uint32_t)m_tx_buf;
//obj->spis->RXDPTR = (uint32_t)m_rx_buf;
obj->spis->TASKS_RELEASE=1;
}