I want to use 5 Gpios as user input buttons in mqx TWRK60D100. I followed configuration as
Today, it’s time for us to combine inputs and outputs into the same script. It’s nothing scary and it’s not new either. It’s simply a case of doing what we’ve already done in the last two days’ of GPIO basics, but combining them. To make it super-easy, we’ll even stick to the same port.
Interrupt handling of different pins say
(GPIO_PORT_E | GPIO_PIN26) ,(GPIO_PORT_A | GPIO_PIN19)
worked fine.But from (GPIO_PORT_C | GPIO_PIN5), (GPIO_PORT_C | GPIO_PIN4), (GPIO_PORT_C | GPIO_PIN1),
only last configured (GPIO_PORT_C | GPIO_PIN1)
was only worked.Other pin's interrupt handler get executes repeatedly without clearing interrupt flag.When i commented (GPIO_PORT_C | GPIO_PIN1)
pin configuration, (GPIO_PORT_C | GPIO_PIN4)
worked fine but problem remained with (GPIO_PORT_C | GPIO_PIN5).
When I looked the address of pin in the interrupt handler, all of the port c interrupts show the address of last configured
GPIO C PIN1
.What could be wrong with my code?
How to configure interrupt handler for different pins of same port?
artless noise15.9k44 gold badges4949 silver badges8080 bronze badges
ShihabShihab
Is this question similar to what you get asked at work? Learn more about asking and sharing private information with your coworkers using Stack Overflow for Teams.
Browse other questions tagged cinterrupt-handlinggpiomqx or ask your own question.
Permalink
Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign up Find file Copy path
Cannot retrieve contributors at this time
//------------------------------------------------------------------------------ |
// Copyright (c) 2016 by Lukasz Janyst <[email protected]> |
//------------------------------------------------------------------------------ |
// This file is part of silly-invaders. |
// |
// silly-invaders is free software: you can redistribute it and/or modify |
// it under the terms of the GNU General Public License as published by |
// the Free Software Foundation, either version 3 of the License, or |
// (at your option) any later version. |
// |
// silly-invaders is distributed in the hope that it will be useful, |
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// GNU General Public License for more details. |
// |
// You should have received a copy of the GNU General Public License |
// along with silly-invaders. If not, see <http://www.gnu.org/licenses/>. |
//------------------------------------------------------------------------------ |
#include<io/IO_device.h> |
#include<io/IO_error.h> |
#include'TM4C.h' |
#include'TM4C_dma.h' |
#include'TM4C_gpio.h' |
//------------------------------------------------------------------------------ |
// Hardware info for SSI |
//------------------------------------------------------------------------------ |
struct ssi_data { |
uint8_t gpio_port; |
uint8_t gpio_pin_clk; |
uint8_t gpio_pin_fss; |
uint8_t gpio_pin_rx; |
uint8_t gpio_pin_tx; |
uint8_t gpio_pin_afsel; |
uint8_t interrupt_num; |
uint8_t dma_channel_rx; |
uint8_t dma_channel_tx; |
uint8_t dma_channel_enc; |
}; |
staticconststruct ssi_data ssi_info[] = { |
{GPIO_PORTA_NUM, GPIO_PIN2_NUM, GPIO_PIN3_NUM, GPIO_PIN4_NUM, GPIO_PIN5_NUM, 2, 7, 10, 11, 0}, |
{GPIO_PORTF_NUM, GPIO_PIN2_NUM, GPIO_PIN3_NUM, GPIO_PIN0_NUM, GPIO_PIN1_NUM, 2, 34, 10, 11, 1}, |
{GPIO_PORTB_NUM, GPIO_PIN4_NUM, GPIO_PIN5_NUM, GPIO_PIN6_NUM, GPIO_PIN7_NUM, 2, 57, 12, 13, 2}, |
{GPIO_PORTD_NUM, GPIO_PIN0_NUM, GPIO_PIN1_NUM, GPIO_PIN2_NUM, GPIO_PIN3_NUM, 1, 58, 14, 15, 2}, |
}; |
//------------------------------------------------------------------------------ |
// IO devices |
//------------------------------------------------------------------------------ |
staticstruct IO_io *ssi_devices[4]; |
//------------------------------------------------------------------------------ |
// Handle uart interrupt |
//------------------------------------------------------------------------------ |
staticvoidssi_handler(uint8_t module) |
{ |
uint16_t events = 0; |
uint32_t module_offset = module * SSI_MODULE_OFFSET; |
if(SSI_REG(module_offset, SSI_MIS) & 0x04) events |= IO_EVENT_READ; |
if(SSI_REG(module_offset, SSI_MIS) & 0x08) events |= IO_EVENT_WRITE; |
//---------------------------------------------------------------------------- |
// No known events but we have still been called. Check if we got a DMA |
// interrupt |
//---------------------------------------------------------------------------- |
if(!events) { |
uint8_t channel_rx = ssi_info[module].dma_channel_rx; |
uint8_t channel_tx = ssi_info[module].dma_channel_tx; |
uint8_t enc = ssi_info[module].dma_channel_enc; |
if(TM4C_dma_check_interrupt(channel_rx, enc)) |
events |= IO_EVENT_DMA_READ; |
if(TM4C_dma_check_interrupt(channel_tx, enc)) |
events |= IO_EVENT_DMA_WRITE; |
} |
//---------------------------------------------------------------------------- |
// Call the user handler |
//---------------------------------------------------------------------------- |
if(ssi_devices[module] && ssi_devices[module]->event) |
ssi_devices[module]->event(ssi_devices[module], events); |
} |
//------------------------------------------------------------------------------ |
// Interrupt handlers |
//------------------------------------------------------------------------------ |
voidssi0_handler() { ssi_handler(0); } |
voidssi1_handler() { ssi_handler(1); } |
voidssi2_handler() { ssi_handler(2); } |
voidssi3_handler() { ssi_handler(3); } |
//------------------------------------------------------------------------------ |
// Write to given SSI |
//------------------------------------------------------------------------------ |
staticint32_tssi_write_normal(IO_io *io, constvoid *data, uint32_t length) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
uint8_t byte = 1; |
if((SSI_REG(ssi_offset, SSI_CR0) & 0x0f) > 7) |
byte = 0; |
constuint8_t *b_data8 = data; |
constuint16_t *b_data16 = data; |
for(uint32_t i = 0; i < length; ++i) { |
// we cannot write if TNF is 0 |
if(io->flags & IO_NONBLOCKING) { |
if((SSI_REG(ssi_offset, SSI_SR) & 0x02) 0) { |
if(i 0) return -IO_EWOULDBLOCK; |
elsereturn i; |
} |
} |
else |
while((SSI_REG(ssi_offset, SSI_SR) & 0x02) 0); |
if(byte) |
SSI_REG(ssi_offset, SSI_DR) = b_data8[i]; |
else |
SSI_REG(ssi_offset, SSI_DR) = b_data16[i]; |
} |
return length; |
} |
//------------------------------------------------------------------------------ |
// Read from given SSI |
//------------------------------------------------------------------------------ |
staticint32_tssi_read_normal(IO_io *io, void *data, uint32_t length) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
uint8_t byte = 1; |
if((SSI_REG(ssi_offset, SSI_CR0) & 0x0f) > 7) |
byte = 0; |
uint8_t *b_data8 = data; |
uint16_t *b_data16 = data; |
for(uint32_t i = 0; i < length; ++i) { |
// we cannot read if RNE is 0 |
if(io->flags & IO_NONBLOCKING) { |
if((SSI_REG(ssi_offset, SSI_SR) & 0x04) 0) { |
if(i 0) return -IO_EWOULDBLOCK; |
elsereturn i; |
} |
} |
else |
while((SSI_REG(ssi_offset, SSI_SR) & 0x04) 0); |
if(byte) |
b_data8[i] = SSI_REG(ssi_offset, SSI_DR) & 0xff; |
else |
b_data16[i] = SSI_REG(ssi_offset, SSI_DR) & 0xffff; |
} |
return length; |
} |
//------------------------------------------------------------------------------ |
// Transfer data to SSI using DMA |
//------------------------------------------------------------------------------ |
staticint32_tssi_write_dma(IO_io *io, constvoid *data, uint32_t length) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
uint8_t dma_channel = ssi_info[io->channel].dma_channel_tx; |
uint8_t dma_enc = ssi_info[io->channel].dma_channel_enc; |
dma_control *ctrl = TM4C_dma_get_control(dma_channel, DMA_TYPE_PRIMARY); |
//---------------------------------------------------------------------------- |
// Check whether the DMA channel is ready for a transfer |
//---------------------------------------------------------------------------- |
if(io->flags & IO_NONBLOCKING) { |
if(ctrl->control & 0x03) |
return -IO_EWOULDBLOCK; |
} |
else |
while(ctrl->control & 0x03); |
//---------------------------------------------------------------------------- |
// Set the channel control up |
//---------------------------------------------------------------------------- |
if(length 0) |
return0; |
if(length > 1024) |
length = 1024; |
uint8_t byte = 1; |
if((SSI_REG(ssi_offset, SSI_CR0) & 0x0f) > 7) |
byte = 0; |
if(byte) |
ctrl->src = ((uint8_t *)data)+(length-1); // last item of the buffer |
else { |
ctrl->src = ((uint16_t *)data)+(length-1); // last item of the buffer |
ctrl->control |= (0x01 << 28); // destination item size is |
// a half-word |
ctrl->control |= (0x01 << 26); // source increments by a |
// half-word |
ctrl->control |= (0x01 << 24); // source item data size is |
// a half-word |
} |
ctrl->dst = (void *)&SSI_REG(ssi_offset, SSI_DR); |
ctrl->control = 0; |
ctrl->control |= (0x03 << 30); // destination does not increment |
ctrl->control |= (0x02 << 14); // arbitration size is 4 transfers |
// interrupt trigger level for FIFO |
ctrl->control |= ((length-1) << 4); // transfer size, up to 1024 items |
ctrl->control |= 0x01; // basic transfer mode |
TM4C_dma_run_transfer(dma_channel, dma_enc); |
return length; |
} |
//------------------------------------------------------------------------------ |
// Get data from SSI using dma |
//------------------------------------------------------------------------------ |
staticint32_tssi_read_dma(IO_io *io, void *data, uint32_t length) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
uint8_t dma_channel = ssi_info[io->channel].dma_channel_rx; |
uint8_t dma_enc = ssi_info[io->channel].dma_channel_enc; |
dma_control *ctrl = TM4C_dma_get_control(dma_channel, DMA_TYPE_PRIMARY); |
//---------------------------------------------------------------------------- |
// Check whether the DMA channel is ready for a transfer |
//---------------------------------------------------------------------------- |
if(io->flags & IO_NONBLOCKING) { |
if(ctrl->control & 0x03) |
return -IO_EWOULDBLOCK; |
} |
else |
while(ctrl->control & 0x03); |
//---------------------------------------------------------------------------- |
// Set the channel control up |
//---------------------------------------------------------------------------- |
if(length 0) |
return0; |
if(length > 1024) |
length = 1024; |
uint8_t byte = 1; |
if((SSI_REG(ssi_offset, SSI_CR0) & 0x0f) > 7) |
byte = 0; |
ctrl->control = 0; |
ctrl->src = (void *)&SSI_REG(ssi_offset, SSI_DR); |
if(byte) |
ctrl->dst = ((uint8_t *)data)+(length-1); // last byte of the buffer |
else { |
ctrl->dst = ((uint16_t *)data)+(length-1); // last item of the buffer |
ctrl->control |= (0x01 << 30); // destination increments by a |
// half-word |
ctrl->control |= (0x01 << 28); // destination item size is |
// a half-word |
ctrl->control |= (0x01 << 24); // source item data size is |
// a half-word |
} |
ctrl->control |= (0x03 << 26); // source does not increment |
ctrl->control |= (0x02 << 14); // arbitration size is 4 transfers |
// interrupt trigger level for FIFO |
ctrl->control |= ((length-1) << 4); // transfer size, up to 1024 items |
ctrl->control |= 0x01; // basic transfer mode |
TM4C_dma_run_transfer(dma_channel, dma_enc); |
return length; |
} |
//------------------------------------------------------------------------------ |
// Sync ssi |
//------------------------------------------------------------------------------ |
staticint32_tssi_sync(IO_io *io) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
// the busy bit is set untill the last byte from the TX FIFO has been |
// transmitted |
while(SSI_REG(ssi_offset, SSI_SR) & 0x10); |
return0; |
} |
//------------------------------------------------------------------------------ |
// Initialize given SSI module |
//------------------------------------------------------------------------------ |
int32_tIO_ssi_init(IO_io *io, uint8_t module, uint16_t flags, |
IO_ssi_attrs *attrs) |
{ |
if(module > 7) |
return -IO_EINVAL; |
if(!io) |
return -IO_EINVAL; |
if(attrs->master && (attrs->bandwidth < 1231 || attrs->bandwidth > 40000000)) |
return -IO_EINVAL; |
if(attrs->frame_format < 0 || attrs->frame_format > 3) |
return -IO_EINVAL; |
if(attrs->frame_size < 4 || attrs->frame_size > 16) |
return -IO_EINVAL; |
//---------------------------------------------------------------------------- |
// Initialize the hardware |
//---------------------------------------------------------------------------- |
uint8_t port = ssi_info[module].gpio_port; |
uint8_t clk = ssi_info[module].gpio_pin_clk; |
uint8_t fss = ssi_info[module].gpio_pin_fss; |
uint8_t rx = ssi_info[module].gpio_pin_rx; |
uint8_t tx = ssi_info[module].gpio_pin_tx; |
uint8_t afsel = ssi_info[module].gpio_pin_afsel; |
uint16_t ssi_offset = module * SSI_MODULE_OFFSET; |
// enable the ssi clock |
RCGCSSI_REG |= (1 << module); |
//---------------------------------------------------------------------------- |
// Set the GPIO up |
//---------------------------------------------------------------------------- |
TM4C_gpio_port_init(port); |
if(module 1) |
TM4C_gpio_pin_unlock(port, rx); |
uint8_t out = 1; |
if(!attrs->master) |
out = 0; |
TM4C_gpio_pin_init(port, clk, afsel, 0, out); |
TM4C_gpio_pin_init(port, fss, afsel, 0, out); |
TM4C_gpio_pin_init(port, rx, afsel, 0, 0); |
TM4C_gpio_pin_init(port, tx, afsel, 0, 1); |
//---------------------------------------------------------------------------- |
// Configure SSI |
//---------------------------------------------------------------------------- |
// calculate the desired clock parameters |
uint32_tclock = 80000000/attrs->bandwidth; |
uint32_t prescale = 2; |
for(; clock/prescale > 256; prescale *= 2); |
uint32_t scr = clock/prescale - 1; |
// disable ssi |
SSI_REG(ssi_offset, SSI_CR1) &= ~0x02; |
// master/slave? |
if(attrs->master) { |
SSI_REG(ssi_offset, SSI_CR1) &= ~0x04; |
// clock |
SSI_REG(ssi_offset, SSI_CPSR) = prescale & 0xff; |
SSI_REG(ssi_offset, SSI_CR0) &= ~(0xff << 8); |
SSI_REG(ssi_offset, SSI_CR0) |= ((scr & 0xff) << 8); |
} |
else { |
SSI_REG(ssi_offset, SSI_CR1) |= 0x04; |
// slave output |
if(attrs->slave_out) |
SSI_REG(ssi_offset, SSI_CR1) &= ~0x08; |
else |
SSI_REG(ssi_offset, SSI_CR1) |= 0x08; |
} |
// system clock as the clock source |
SSI_REG(ssi_offset, SSI_CC) &= ~0x0f; |
// frame format |
uint8_t format; |
if(attrs->frame_format SSI_FRAME_FREESCALE) format = 0; |
elseif(attrs->frame_format SSI_FRAME_TEXAS) format = 1; |
elseif(attrs->frame_format SSI_FRAME_MICROWIRE) format = 2; |
SSI_REG(ssi_offset, SSI_CR0) &= ~(0x3 << 4); |
SSI_REG(ssi_offset, SSI_CR0) |= (format << 4); |
if(attrs->frame_format SSI_FRAME_FREESCALE) { |
if(attrs->freescale_spo) |
SSI_REG(ssi_offset, SSI_CR0) |= (1 << 6); |
else |
SSI_REG(ssi_offset, SSI_CR0) &= ~(1 << 6); |
if(attrs->freescale_sph) |
SSI_REG(ssi_offset, SSI_CR0) |= (1 << 7); |
else |
SSI_REG(ssi_offset, SSI_CR0) &= ~(1 << 7); |
} |
// frame size |
SSI_REG(ssi_offset, SSI_CR0) &= ~0x0f; |
SSI_REG(ssi_offset, SSI_CR0) |= ((attrs->frame_size-1) & 0x0f); |
if(flags & IO_DMA) |
SSI_REG(ssi_offset, SSI_DMACTL) |= 0x03; |
// remove the garbage from the incoming queue |
uint8_t byte; |
while(SSI_REG(ssi_offset, SSI_SR) & 0x04) |
byte = SSI_REG(ssi_offset, SSI_DR); |
(void)byte; |
// enable ssi |
SSI_REG(ssi_offset, SSI_CR1) |= 0x02; |
//---------------------------------------------------------------------------- |
// Initialize the software |
//---------------------------------------------------------------------------- |
io->channel = module; |
io->flags = flags; |
io->type = IO_SSI; |
io->event = 0; |
io->sync = ssi_sync; |
ssi_devices[module] = io; |
//---------------------------------------------------------------------------- |
// Normal read/write |
//---------------------------------------------------------------------------- |
if(!(flags & IO_DMA)) { |
io->write = ssi_write_normal; |
io->read = ssi_read_normal; |
} |
else { |
io->write = ssi_write_dma; |
io->read = ssi_read_dma; |
} |
//---------------------------------------------------------------------------- |
// Enable the interrupt if needed |
//---------------------------------------------------------------------------- |
if(flags & IO_ASYNC) |
TM4C_enable_interrupt(ssi_info[module].interrupt_num, 7); |
return0; |
} |
//------------------------------------------------------------------------------ |
// Enable events on SSI device |
//------------------------------------------------------------------------------ |
int32_tTM4C_ssi_event_enable(IO_io *io, uint16_t events) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
if(events & IO_EVENT_READ) SSI_REG(ssi_offset, SSI_IM) |= 0x04; |
if(events & IO_EVENT_WRITE) SSI_REG(ssi_offset, SSI_IM) |= 0x08; |
return0; |
} |
//------------------------------------------------------------------------------ |
// Disable events on SSI device |
//------------------------------------------------------------------------------ |
int32_tTM4C_ssi_event_disable(IO_io *io, uint16_t events) |
{ |
uint32_t ssi_offset = io->channel*SSI_MODULE_OFFSET; |
if(events & IO_EVENT_READ) SSI_REG(ssi_offset, SSI_IM) &= ~0x08; |
if(events & IO_EVENT_WRITE) SSI_REG(ssi_offset, SSI_IM) &= ~0x04; |
return0; |
} |
Copy lines Copy permalink