* [ECOS] Re: Problem setting up an ISR for a K60 PORT [not found] <A60E30AB-6F4C-4A0E-8B39-BC76435B33D2@linear.com> @ 2013-02-19 8:34 ` Lambrecht Jürgen 2013-02-19 14:51 ` Michael Jones 0 siblings, 1 reply; 4+ messages in thread From: Lambrecht Jürgen @ 2013-02-19 8:34 UTC (permalink / raw) To: Michael Jones; +Cc: ecos-devel, ecos Hi Michael, first of all, I think your message should be sent to ecos-discuss instead (so I put it in cc). I put some comments below - it is a long time ago I coded ISR/DSR, so I just looked to some working code of ours to compare. On 02/19/2013 01:12 AM, Michael Jones wrote: > I am struggling to setup an ISR/DSR for a PORT on the K60. My goal is to get an ISR/DSR when Pin 19 of PORTA transitions from high to low. This is pin PTA19 of the device. > > My non-working code and complete code below. > > What the code tries to do is setup PORTA PIN19 as input. Then take the PCR register and set the interrupt to work off a falling edge. > > Then create the ISR/DSR. > > When I toggle the pin, nothing happens. > > FYI the hardware works with MQX, so I know the hardware is ok. I use it the same way under MQX where I get an ISR from a negative edge. And I have put a scope on it to make sure there is an edge. So I am quite sure the problem is the code. > > This code was generated by trying to understand the Kinetis code, but things were not clear to me. Some macros use __pin to mean different things. So this is my best guess. > > Does anyone know how to do this? > > PORT SETUP CODE > ================ > > cyghwr_hal_kinetis_port_t *port_p; > > CYGHWR_HAL_KINETIS_GPIO_PIN_DDR_IN(ALERT_PORT, ALERT_PIN); > > // Get address for PORTA > port_p = Ports[0]; > > // 0xA means interrupt on falling edge. > // Read modify write PCR > port_p->pcr[ALERT_PIN] = > (port_p->pcr[ALERT_PIN]& 0xFFF0FFFF) | > (0xA<< 16); > > // Create an ISR/DSR for PORTA. > // Assuming the priority is what the DSR will run at. > // No data passed. > cyg_interrupt_create( > CYGNUM_HAL_INTERRUPT_PORTA, // Vector > 3, // Priority > (cyg_addrword_t)0, // Data > alert_isr, // ISR > alert_dsr, // DSR > &alert_handle, // Handle > &alert_interrupt); // INTR > cyg_thread_suspend(cyg_thread_self()); After our 'interrupt_create', we also have those calls (we use IRQ2 instead of your PORTA): cyg_interrupt_attach(t_intrhandle); cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_IRQ2, TLV_FALSE, TLV_FALSE); cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_IRQ2); cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_IRQ2); Why do you call 'cyg_thread_suspend...' ? I do not see code that creates a thread. And when I create a thread, I do cyg_thread_create(...); cyg_thread_resume(..);. Why do you need a thread when your code is run by interrupts? > } > > ALL CODE > ========= > > #ifndef ALERT_H_ > #define ALERT_H_ > > #include<cyg/kernel/kapi.h> > #include<cyg/hal/var_io_gpio.h> > #include<cyg/hal/drv_api.h> > #include<cyg/hal/var_io.h> > > #define ALERT_PORT A > #define ALERT_PIN 19 > > extern void start_alert(cyg_addrword_t data); > > #endif > > #include "alert.h" > > cyg_handle_t alert_handle; > cyg_interrupt alert_interrupt; > > cyghwr_hal_kinetis_port_t * const Ports[] = { > CYGHWR_HAL_KINETIS_PORTA_P, CYGHWR_HAL_KINETIS_PORTB_P, > CYGHWR_HAL_KINETIS_PORTC_P, CYGHWR_HAL_KINETIS_PORTD_P, > CYGHWR_HAL_KINETIS_PORTE_P > }; > > cyg_uint32 alert_isr( cyg_vector_t vector, > cyg_addrword_t data > ) > { > return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; No need for: cyg_interrupt_mask(CYGNUM_HAL_INTERRUPT_IRQ2); cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_IRQ2); ? > } > > void alert_dsr( cyg_vector_t vector, > cyg_ucount32 count, > cyg_addrword_t data > ) > { I guess you still need to add code here. No need for this at the end: cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_IRQ2); ? I hope this helps. Kind regards, Jürgen > } > > void pmbus_alert_callback(void) > { > > > } > > void start_alert(cyg_addrword_t data) > { > cyghwr_hal_kinetis_port_t *port_p; > > CYGHWR_HAL_KINETIS_GPIO_PIN_DDR_IN(ALERT_PORT, ALERT_PIN); > > // Get address for PORTA > port_p = Ports[0]; > > // 0xA means interrupt on falling edge. > // Read modify write PCR > port_p->pcr[ALERT_PIN] = > (port_p->pcr[ALERT_PIN]& 0xFFF0FFFF) | > (0xA<< 16); > > // Create an ISR/DSR for PORTA. > // Assuming the priority is what the DSR will run at. > // No data passed. > cyg_interrupt_create( > CYGNUM_HAL_INTERRUPT_PORTA, // Vector > 3, // Priority > (cyg_addrword_t)0, // Data > alert_isr, // ISR > alert_dsr, // DSR > &alert_handle, // Handle > &alert_interrupt); // INTR > cyg_thread_suspend(cyg_thread_self()); > } > > -- Jürgen Lambrecht R&D Associate Tel: +32 (0)51 303045 Fax: +32 (0)51 310670 http://www.televic-rail.com Televic Rail NV - Leo Bekaertlaan 1 - 8870 Izegem - Belgium Company number 0825.539.581 - RPR Kortrijk -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss ^ permalink raw reply [flat|nested] 4+ messages in thread
* [ECOS] Re: Problem setting up an ISR for a K60 PORT 2013-02-19 8:34 ` [ECOS] Re: Problem setting up an ISR for a K60 PORT Lambrecht Jürgen @ 2013-02-19 14:51 ` Michael Jones 2013-02-19 19:30 ` Ilija Kocho 0 siblings, 1 reply; 4+ messages in thread From: Michael Jones @ 2013-02-19 14:51 UTC (permalink / raw) To: Lambrecht Jürgen; +Cc: ecos-devel, ecos >> >> > After our 'interrupt_create', we also have those calls (we use IRQ2 > instead of your PORTA): > cyg_interrupt_attach(t_intrhandle); > cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_IRQ2, TLV_FALSE, TLV_FALSE); > cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_IRQ2); > cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_IRQ2); > > Why do you call 'cyg_thread_suspend...' ? I do not see code that creates > a thread. And when I create a thread, I do cyg_thread_create(...); > cyg_thread_resume(..);. > > Why do you need a thread when your code is run by interrupts? I am creating all my threads from cyg_user_start. Each "task" (thread) has its own file and interface (psuedo OO). The overall app has multiple threads, one of them handling telemetry, and a higher priority one handling ALERTB problems using a PMBus (I2C). Once the interrupt works and the DSR is called, the DSR code will do an ARA (get addresses vis I2C), get STATUS_WORD for all address that ALERTed, and then send events so that the alert thread can respond by interacting over the PMBus. I just suspended the thread until I get the ISR to work, then I will add then event and processing code. I could do all the work in the DSR as long as I can call I2C from the DSR. However, I am porting an application from MQX and maintaining its structure, and in MQX I don't have a DSR, so in that version the ARA and read of STATUS_WORD is all in the task code. I tried making some I2C calls from a DSR by using a timer, and the code locked up somewhere. I did not have time to track down the problem. It could have gotten in trouble on a mutex, in the driver, etc. So I may have to put all the code in the task/thread anyway until I have a better understanding of what code can execute in the DSR. I just have to dig through the eCos Ref Manual. Seeing your code, brought something to mind. I had assumed that the interrupt was enabled in the Kinetis HAL and all I had to do was configure the port. Perhaps that is not the case. I'll try to use your example and see what happens. Thanks -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [ECOS] Re: Problem setting up an ISR for a K60 PORT 2013-02-19 14:51 ` Michael Jones @ 2013-02-19 19:30 ` Ilija Kocho 2013-02-20 5:19 ` [ECOS] " Michael Jones 0 siblings, 1 reply; 4+ messages in thread From: Ilija Kocho @ 2013-02-19 19:30 UTC (permalink / raw) To: Michael Jones; +Cc: ecos Mike There isn't a general interrupt enable in Kinetis HAL. Actually there's no GPIO interrupt support yet. Just one note regarding interrupt priority numbering. Kinetis implements 4 bits, and by Cortex-M interrupt priority arbitration scheme it's 4 most significant bits (out of 8). Therefore your interrupt priority should be something like 0x30. Priority 3 effectively is same as 0. For relevant Kinetis priority numbers look for /Interrupt Priority Scheme/ in configtool. Ilija On 19.02.2013 15:51, Michael Jones wrote: >>> >> After our 'interrupt_create', we also have those calls (we use IRQ2 >> instead of your PORTA): >> cyg_interrupt_attach(t_intrhandle); >> cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_IRQ2, TLV_FALSE, TLV_FALSE); >> cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_IRQ2); >> cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_IRQ2); >> >> Why do you call 'cyg_thread_suspend...' ? I do not see code that creates >> a thread. And when I create a thread, I do cyg_thread_create(...); >> cyg_thread_resume(..);. >> >> Why do you need a thread when your code is run by interrupts? > > Seeing your code, brought something to mind. I had assumed that the interrupt was enabled in the Kinetis HAL and all I had to do was configure the port. Perhaps that is not the case. I'll try to use your example and see what happens. Indeed, there isn't a general interrupt enable in Kinetis HAL. > > Thanks > > -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [ECOS] Problem setting up an ISR for a K60 PORT 2013-02-19 19:30 ` Ilija Kocho @ 2013-02-20 5:19 ` Michael Jones 0 siblings, 0 replies; 4+ messages in thread From: Michael Jones @ 2013-02-20 5:19 UTC (permalink / raw) To: Ilija Kocho; +Cc: ecos Thanks for the help. I have put working code below. I will now try to move the code to the Kinetis HAL. Is there any GPIO/PORT API in the HAL I should be aware of? Include file --------------- #ifndef ALERT_H_ #define ALERT_H_ #include <cyg/kernel/kapi.h> #include <cyg/hal/var_io_gpio.h> #include <cyg/hal/drv_api.h> #include <cyg/hal/var_io.h> #define ALERT_PORT A #define ALERT_PIN 19 #define CYGHWR_HAL_KINETIS_GPIO_PORTA_C ((cyghwr_hal_kinetis_gpio_t*)0x40049000u) #define CYGHWR_HAL_KINETIS_GPIO_PORTB_C ((cyghwr_hal_kinetis_gpio_t*)0x4004A040u) #define CYGHWR_HAL_KINETIS_GPIO_PORTC_C ((cyghwr_hal_kinetis_gpio_t*)0x4004B080u) #define CYGHWR_HAL_KINETIS_GPIO_PORTD_C ((cyghwr_hal_kinetis_gpio_t*)0x4004C0C0u) #define CYGHWR_HAL_KINETIS_GPIO_PORTE_C ((cyghwr_hal_kinetis_gpio_t*)0x4004D100u) #define CYGHWR_HAL_KINETIS_GPIO_DDR_GET(__port) \ CYGHWR_HAL_KINETIS_GPIO(__port, pddr) #define CYG_HAL_KINETIS_GPIO_ISFR(__port) \ *((cyg_uint32*)(((cyg_uint32)CYGHWR_HAL_KINETIS_GPIO_PORT##__port##_C) + ((cyg_uint32)0xA0))) #define CYGHWR_HAL_KINETIS_GPIO_ISFR_CLEAR(__port, __pin) \ CYG_HAL_KINETIS_GPIO_ISFR(__port) |= BIT_(__pin) #define CYGHWR_HAL_KINETIS_GPIO_IFSR_GET(__port) \ CYG_HAL_KINETIS_GPIO_ISFR(__port) extern void start_alert(cyg_addrword_t data); #endif code file ------------ #include "alert.h" cyg_handle_t alert_handle; cyg_interrupt alert_interrupt; cyghwr_hal_kinetis_port_t * const Ports[] = { CYGHWR_HAL_KINETIS_PORTA_P, CYGHWR_HAL_KINETIS_PORTB_P, CYGHWR_HAL_KINETIS_PORTC_P, CYGHWR_HAL_KINETIS_PORTD_P, CYGHWR_HAL_KINETIS_PORTE_P }; cyg_uint32 alert_isr( cyg_vector_t vector, cyg_addrword_t data ) { cyghwr_hal_kinetis_port_t *port_p; cyg_uint32 *pifsr; cyg_uint32 ifsr; cyg_uint32 *ppcr; cyg_uint32 pcr; cyg_interrupt_mask(CYGNUM_HAL_INTERRUPT_PORTA); port_p = Ports[0]; pifsr = &CYGHWR_HAL_KINETIS_GPIO_IFSR_GET(ALERT_PORT); ifsr = CYGHWR_HAL_KINETIS_GPIO_IFSR_GET(ALERT_PORT); ppcr = &port_p->pcr[ALERT_PIN]; pcr = port_p->pcr[ALERT_PIN]; // No HAL implementation for this //cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PORTA); { // Manual implementation of cyg_interrupt_acknowledge // Get address for PORTA port_p->pcr[ALERT_PIN] |= BIT_(24); CYGHWR_HAL_KINETIS_GPIO_ISFR_CLEAR(ALERT_PORT, ALERT_PIN); } return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR; } void alert_dsr( cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data ) { cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PORTA); } void pmbus_alert_callback(void) { } void start_alert(cyg_addrword_t data) { cyghwr_hal_kinetis_port_t *port_p; // Create an ISR/DSR for PORTA. // Assuming the priority is what the DSR will run at. // No data passed. // This is normally done at setup before things run, so this code may need // to move to cyg_user_start() or disable other interrupts while doing this. // Priority 0xA is lower than I2C so that transactions can complete without an // ALERTB interfering, but higher than the Real Time clock, etc. cyg_interrupt_create( CYGNUM_HAL_INTERRUPT_PORTA, // Vector 0xA0, // Priority (cyg_addrword_t)0, // Data alert_isr, // ISR alert_dsr, // DSR &alert_handle, // Handle &alert_interrupt); // INTR cyg_interrupt_attach(alert_handle); //cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_PORTA, true, true); { // Manual implementation of cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_PORTA, true, true); CYGHWR_HAL_KINETIS_GPIO_PIN_DDR_IN(ALERT_PORT, ALERT_PIN); // Get address for PORTA port_p = Ports[0]; // Neg Edge No Lock GPIO port_p->pcr[ALERT_PIN] = (0xA << 16) | (0 << 15) | (0x1 << 8) | 0x00; // Print registers for debug. printf("PDDR 0x%x 0x%x\n", &CYGHWR_HAL_KINETIS_GPIO_DDR_GET(ALERT_PORT), CYGHWR_HAL_KINETIS_GPIO_DDR_GET(ALERT_PORT)); printf("PCR 0x%x 0x%x\n", &port_p->pcr[ALERT_PIN], port_p->pcr[ALERT_PIN]); } // No HAL implementation for this //cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_PORTA); // In case the default is masked. cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_PORTA); cyg_thread_suspend(cyg_thread_self()); } On Feb 19, 2013, at 12:29 PM, Ilija Kocho <ilijak@siva.com.mk> wrote: > Mike > > There isn't a general interrupt enable in Kinetis HAL. Actually there's > no GPIO interrupt support yet. > > Just one note regarding interrupt priority numbering. Kinetis implements > 4 bits, and by Cortex-M interrupt priority arbitration scheme it's 4 > most significant bits (out of 8). Therefore your interrupt priority > should be something like 0x30. Priority 3 effectively is same as 0. For > relevant Kinetis priority numbers look for /Interrupt Priority Scheme/ > in configtool. > > Ilija > > > On 19.02.2013 15:51, Michael Jones wrote: >>>> >>> After our 'interrupt_create', we also have those calls (we use IRQ2 >>> instead of your PORTA): >>> cyg_interrupt_attach(t_intrhandle); >>> cyg_interrupt_configure(CYGNUM_HAL_INTERRUPT_IRQ2, TLV_FALSE, TLV_FALSE); >>> cyg_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_IRQ2); >>> cyg_interrupt_unmask(CYGNUM_HAL_INTERRUPT_IRQ2); >>> >>> Why do you call 'cyg_thread_suspend...' ? I do not see code that creates >>> a thread. And when I create a thread, I do cyg_thread_create(...); >>> cyg_thread_resume(..);. >>> >>> Why do you need a thread when your code is run by interrupts? >> >> Seeing your code, brought something to mind. I had assumed that the interrupt was enabled in the Kinetis HAL and all I had to do was configure the port. Perhaps that is not the case. I'll try to use your example and see what happens. > > Indeed, there isn't a general interrupt enable in Kinetis HAL. > > >> >> Thanks >> >> > > > -- > Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos > and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss > -- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-02-20 5:19 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- [not found] <A60E30AB-6F4C-4A0E-8B39-BC76435B33D2@linear.com> 2013-02-19 8:34 ` [ECOS] Re: Problem setting up an ISR for a K60 PORT Lambrecht Jürgen 2013-02-19 14:51 ` Michael Jones 2013-02-19 19:30 ` Ilija Kocho 2013-02-20 5:19 ` [ECOS] " Michael Jones
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).