Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SPI: Implemented MISO, MOSI, SCK and SS pins handling using avr_bitba… #249

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega128.c
Expand Up @@ -391,7 +391,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(0, 0, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega1280.c
Expand Up @@ -616,7 +616,7 @@ const struct mcu_t {
},

},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega1281.c
Expand Up @@ -431,7 +431,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega128rfr2.c
Expand Up @@ -469,7 +469,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega169.c
Expand Up @@ -319,7 +319,7 @@ const struct mcu_t {
},
},
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'B', 1, 3, 2, 0),
};

static avr_t * make()
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega2560.c
Expand Up @@ -618,7 +618,7 @@ const struct mcu_t {
},

},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megax.h
Expand Up @@ -301,7 +301,7 @@ const struct mcu_t SIM_CORENAME = {
},
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(0, 0, 'B', 7, 6, 5, 4),
.twi = {

.r_twcr = TWCR,
Expand Down
4 changes: 2 additions & 2 deletions simavr/cores/sim_megax4.h
Expand Up @@ -432,9 +432,9 @@ const struct mcu_t SIM_CORENAME = {
},
#endif
#ifdef MSTR0 /* xx4a and xx4pa series */
AVR_SPIX_DECLARE(0, PRR0, PRSPI),
AVR_SPIX_DECLARE(0, PRR0, PRSPI, 'B', 7, 6, 5, 4),
#else
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 7, 6, 5, 4),
#endif
.twi = {
.disabled = AVR_IO_REGBIT(PRR0,PRTWI),
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megax8.h
Expand Up @@ -345,7 +345,7 @@ const struct mcu_t SIM_CORENAME = {
}
}
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'B', 5, 4, 3, 2),
.twi = {
.disabled = AVR_IO_REGBIT(PRR,PRTWI),

Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megaxm1.h
Expand Up @@ -311,7 +311,7 @@ const struct mcu_t SIM_CORENAME = {
},
},
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'C', 7, 0, 1, 1),
};
#endif /* SIM_CORENAME */

Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_usb162.c
Expand Up @@ -202,7 +202,7 @@ const struct mcu_t {
},
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 7, 6, 5, 4),
.usb = {
.name='1',
.disabled=AVR_IO_REGBIT(PRR1, PRUSB),// bit in the PRR
Expand Down
38 changes: 38 additions & 0 deletions simavr/sim/avr/avr_mcu_section.h
Expand Up @@ -63,6 +63,7 @@ enum {
AVR_MMCU_TAG_VCD_PORTPIN,
AVR_MMCU_TAG_VCD_IRQ,
AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
AVR_MMCU_TAG_BITBANG,
};

enum {
Expand All @@ -72,6 +73,18 @@ enum {
SIMAVR_CMD_UART_LOOPBACK,
};

#define BITBANG_ON_SPI(_name) \
((uint64_t)(_name >= '0' ? ((1 << (_name - '0'))&0xFF) : (1 << 8)) << 0)

#define BITBANG_ON_UART(_name) \
((uint64_t)((1 << (_name - '0'))&0xFF) << 16)

#define BITBANG_ON_TWI(_name) \
((uint64_t)(1) << 24)

#define BITBANG_ON_LIN(_name) \
((uint64_t)(1) << 32)

#if __AVR__
/*
* WARNING. Due to newer GCC being stupid, they introduced a bug that
Expand All @@ -87,6 +100,12 @@ struct avr_mmcu_long_t {
uint32_t val;
} __attribute__((__packed__));

struct avr_mmcu_longlong_t {
uint8_t tag;
uint8_t len;
uint64_t val;
} __attribute__((__packed__));

struct avr_mmcu_string_t {
uint8_t tag;
uint8_t len;
Expand Down Expand Up @@ -121,6 +140,13 @@ struct avr_mmcu_vcd_trace_t {
#define DO_CONCAT2(_a, _b) _a##_b
#define DO_CONCAT(_a, _b) DO_CONCAT2(_a,_b)

#define AVR_MCU_LONGLONG(_tag, _val) \
const struct avr_mmcu_longlong_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
.tag = _tag,\
.len = sizeof(struct avr_mmcu_longlong_t) - 2,\
.val = _val,\
}

#define AVR_MCU_LONG(_tag, _val) \
const struct avr_mmcu_long_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
.tag = _tag,\
Expand All @@ -131,6 +157,18 @@ struct avr_mmcu_vcd_trace_t {
#define AVR_MCU_BYTE(_tag, _val) \
const uint8_t _##_tag _MMCU_ = { _tag, 1, _val }

/*!
* This Macro allows you turn on or off a bitbang feature for
* peripherals, which support it (plese look code of the corresponding
* module to ensure it's implemented).
* By default bitbang is off for every peripheral.
* You can turn it on using bitmask for specific peripheral instance,
* e.g. the following turns it on for SPI0 and for USART1 in SPI mode:
* AVR_MCU_BITBANG(BITBANG_ON_SPI(0) | BITBANG_ON_SPI('1'));
*/
#define AVR_MCU_BITBANG(_peripheral_on_mask) \
AVR_MCU_LONGLONG(AVR_MMCU_TAG_BITBANG, _peripheral_on_mask)

/*!
* This Macro allows you to specify traces for the VCD file output
* engine. This specifies a default header, and let you fill in the
Expand Down
49 changes: 45 additions & 4 deletions simavr/sim/avr_bitbang.c
Expand Up @@ -29,6 +29,7 @@ extern "C" {

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "avr_bitbang.h"

Expand Down Expand Up @@ -99,7 +100,12 @@ static void avr_bitbang_write_bit(avr_bitbang_t *p)

// output to HW pin
if ( p->p_out.port ) {
avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin), bit);
avr_raise_irq(p->p_out.irq, bit);
uint16_t addr = p->p_out.ioport->r_port;
uint8_t value = (p->avr->data[addr] & ~(1 << p->p_out.pin)) | (!!bit << p->p_out.pin);
// at least avr->data[addr] update is required, otherwise port state is broken
// also triggering vcd signal would be nice here
avr_core_watch_write(p->avr, addr, value);
}

// module callback
Expand Down Expand Up @@ -130,7 +136,12 @@ static void avr_bitbang_clk_edge(avr_bitbang_t *p)

// generate clock output on HW pin
if ( p->clk_generate && p->p_clk.port ) {
avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), clk);
avr_raise_irq(p->p_clk.irq, clk);
uint16_t addr = p->p_clk.ioport->r_port;
uint8_t value = (p->avr->data[addr] & ~(1 << p->p_clk.pin)) | (!!clk << p->p_clk.pin);
// at least avr->data[addr] update is required, otherwise port state is broken
// also triggering vcd signal would be nice here
avr_core_watch_write(p->avr, addr, value);
}

if ( phase ) {
Expand Down Expand Up @@ -175,6 +186,36 @@ static void avr_bitbang_clk_hook(struct avr_irq_t * irq, uint32_t value, void *
avr_bitbang_clk_edge(p);
}

/**
* define bitbang pins
*
* @param p bitbang structure
* @param clk clock pin
* @param in incoming data pin
* @param out outgoing data pin
*/
void avr_bitbang_defpins(avr_bitbang_t * p, avr_iopin_t *clk, avr_iopin_t *in, avr_iopin_t *out)
{
if (clk) {
p->p_clk.port = clk->port;
p->p_clk.pin = clk->pin;
p->p_clk.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", clk->port);
p->p_clk.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin);
}
if (in) {
p->p_in.port = in->port;
p->p_in.pin = in->pin;
p->p_in.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", in->port);
p->p_in.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_in.port ), p->p_in.pin);
}
if (out) {
p->p_out.port = out->port;
p->p_out.pin = out->pin;
p->p_out.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", out->port);
p->p_out.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin);
}
}

/**
* reset bitbang sub-module
*
Expand Down Expand Up @@ -220,7 +261,7 @@ void avr_bitbang_start(avr_bitbang_t * p)
} else {
// slave mode -> attach clock function to clock pin
///@todo test
avr_irq_register_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);
avr_irq_register_notify( p->p_clk.irq, avr_bitbang_clk_hook, p);
}

}
Expand All @@ -238,7 +279,7 @@ void avr_bitbang_stop(avr_bitbang_t * p)

p->enabled = 0;
avr_cycle_timer_cancel(p->avr, avr_bitbang_clk_timer, p);
avr_irq_unregister_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);
avr_irq_unregister_notify( p->p_clk.irq, avr_bitbang_clk_hook, p);
}

#ifdef __cplusplus
Expand Down
25 changes: 22 additions & 3 deletions simavr/sim/avr_bitbang.h
Expand Up @@ -48,6 +48,15 @@
#include "avr_ioport.h"


/**
* pin structure
*/
typedef struct avr_bitbang_iopin_t {
uint16_t port : 8; ///< port e.g. 'B'
uint16_t pin : 8; ///< pin number
avr_ioport_t * ioport;
avr_irq_t * irq;
} avr_bitbang_iopin_t;


/// SPI Module initialization and state structure
Expand All @@ -73,9 +82,9 @@ typedef struct avr_bitbang_t {
uint32_t (*callback_transfer_finished)(uint32_t data, void *param); ///< callback function to notify about a complete transfer
/// (read received data and write new output data)

avr_iopin_t p_clk; ///< clock pin (optional)
avr_iopin_t p_in; ///< data in pin
avr_iopin_t p_out; ///< data out pin
avr_bitbang_iopin_t p_clk; ///< clock pin (optional)
avr_bitbang_iopin_t p_in; ///< data in pin
avr_bitbang_iopin_t p_out; ///< data out pin

// private data
uint32_t data; ///< data buffer
Expand All @@ -92,6 +101,16 @@ typedef struct avr_bitbang_t {
*/
void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p);

/**
* define bitbang pins
*
* @param p bitbang structure
* @param clk clock pin
* @param in incoming data pin
* @param out outgoing data pin
*/
void avr_bitbang_defpins(avr_bitbang_t * p, avr_iopin_t *clk, avr_iopin_t *in, avr_iopin_t *out);

/**
* start bitbang transfer
*
Expand Down